Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| eafe65e321 | |||
| 2acd166437 | |||
| 3d40188217 | |||
| bd0ce7345c | |||
| d3e0cbe8f0 | |||
| 1ec5174820 | |||
| 5c1722b3cb | |||
| f47f4be8e3 | |||
| 60b06a987c | |||
| 769a7ec43a | |||
| 566bf8fff2 | |||
| bf75614190 | |||
| 43bd0e2031 | |||
| 68f897ffe4 | |||
| 3df40214f3 | |||
| 9eda3fd497 | |||
| 9178aeaa9c |
+226
-105
@@ -3,9 +3,9 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: GitHub.Workflow
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: MokoStandards.Release
|
||||
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
|
||||
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API
|
||||
# PATH: /templates/workflows/joomla/auto-release.yml.template
|
||||
# VERSION: 04.06.00
|
||||
# BRIEF: Joomla build & release — ZIP package, updates.xml, SHA-256 checksum
|
||||
@@ -22,13 +22,15 @@
|
||||
# | 4. Update [VERSION: XX.YY.ZZ] badges in markdown files |
|
||||
# | 5. Write updates.xml (Joomla update server XML) |
|
||||
# | 6. Create git tag vXX.YY.ZZ |
|
||||
# | 7a. Patch: update existing GitHub Release for this minor |
|
||||
# | 7a. Patch: update existing Gitea Release for this minor |
|
||||
# | 8. Build ZIP, upload asset, write SHA-256 to updates.xml |
|
||||
# | |
|
||||
# | Every version change: archives main -> version/XX.YY branch |
|
||||
# | Patch 00 = development (no release). First release = patch 01. |
|
||||
# | All patches release (including 00). Patch 00/01 = full pipeline. |
|
||||
# | First release only (patch == 01): |
|
||||
# | 7b. Create new GitHub Release |
|
||||
# | 7b. Create new Gitea Release |
|
||||
# | |
|
||||
# | GitHub mirror: stable/rc releases only (continue-on-error) |
|
||||
# | |
|
||||
# +========================================================================+
|
||||
|
||||
@@ -46,6 +48,9 @@ on:
|
||||
|
||||
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
|
||||
@@ -61,25 +66,26 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
with:
|
||||
token: ${{ secrets.GH_TOKEN || github.token }}
|
||||
token: ${{ secrets.GA_TOKEN }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup MokoStandards tools
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
|
||||
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
|
||||
MOKO_CLONE_TOKEN: ${{ secrets.GA_TOKEN }}
|
||||
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
||||
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN }}"}}'
|
||||
run: |
|
||||
git clone --depth 1 --branch version/04 --quiet \
|
||||
"https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \
|
||||
/tmp/mokostandards
|
||||
cd /tmp/mokostandards
|
||||
git clone --depth 1 --branch main --quiet \
|
||||
"https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoStandards-API.git" \
|
||||
/tmp/mokostandards-api
|
||||
cd /tmp/mokostandards-api
|
||||
composer install --no-dev --no-interaction --quiet
|
||||
|
||||
# -- STEP 1: Read version -----------------------------------------------
|
||||
- name: "Step 1: Read version from README.md"
|
||||
id: version
|
||||
run: |
|
||||
VERSION=$(php /tmp/mokostandards/api/cli/version_read.php --path . 2>/dev/null)
|
||||
VERSION=$(php /tmp/mokostandards-api/cli/version_read.php --path . 2>/dev/null)
|
||||
if [ -z "$VERSION" ]; then
|
||||
echo "No VERSION in README.md — skipping release"
|
||||
echo "skip=true" >> "$GITHUB_OUTPUT"
|
||||
@@ -96,20 +102,16 @@ jobs:
|
||||
echo "branch=version/${MAJOR}" >> "$GITHUB_OUTPUT"
|
||||
echo "minor=$MINOR" >> "$GITHUB_OUTPUT"
|
||||
echo "major=$MAJOR" >> "$GITHUB_OUTPUT"
|
||||
echo "release_tag=v${MAJOR}" >> "$GITHUB_OUTPUT"
|
||||
if [ "$PATCH" = "00" ]; then
|
||||
echo "skip=true" >> "$GITHUB_OUTPUT"
|
||||
echo "is_minor=false" >> "$GITHUB_OUTPUT"
|
||||
echo "Version: $VERSION (patch 00 = development — skipping release)"
|
||||
echo "release_tag=stable" >> "$GITHUB_OUTPUT"
|
||||
# Determine stability for mirror gating
|
||||
echo "stability=stable" >> "$GITHUB_OUTPUT"
|
||||
echo "skip=false" >> "$GITHUB_OUTPUT"
|
||||
if [ "$PATCH" = "00" ] || [ "$PATCH" = "01" ]; then
|
||||
echo "is_minor=true" >> "$GITHUB_OUTPUT"
|
||||
echo "Version: $VERSION (first release for this minor — full pipeline)"
|
||||
else
|
||||
echo "skip=false" >> "$GITHUB_OUTPUT"
|
||||
if [ "$PATCH" = "01" ]; then
|
||||
echo "is_minor=true" >> "$GITHUB_OUTPUT"
|
||||
echo "Version: $VERSION (first release — full pipeline)"
|
||||
else
|
||||
echo "is_minor=false" >> "$GITHUB_OUTPUT"
|
||||
echo "Version: $VERSION (patch — platform version + badges only)"
|
||||
fi
|
||||
echo "is_minor=false" >> "$GITHUB_OUTPUT"
|
||||
echo "Version: $VERSION (patch — platform version + badges only)"
|
||||
fi
|
||||
|
||||
- name: Check if already released
|
||||
@@ -243,7 +245,7 @@ jobs:
|
||||
steps.check.outputs.already_released != 'true'
|
||||
run: |
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
php /tmp/mokostandards/api/cli/version_set_platform.php \
|
||||
php /tmp/mokostandards-api/cli/version_set_platform.php \
|
||||
--path . --version "$VERSION" --branch main
|
||||
|
||||
# -- STEP 4: Update version badges ----------------------------------------
|
||||
@@ -309,7 +311,7 @@ jobs:
|
||||
|
||||
# Build targetplatform (fallback to Joomla 5 if not in manifest)
|
||||
if [ -z "$TARGET_PLATFORM" ]; then
|
||||
TARGET_PLATFORM=$(printf '<targetplatform name="joomla" version="5.*" %s>' "/")
|
||||
TARGET_PLATFORM=$(printf '<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" %s>' "/")
|
||||
fi
|
||||
|
||||
# Build php_minimum tag
|
||||
@@ -318,11 +320,12 @@ jobs:
|
||||
PHP_TAG="<php_minimum>${PHP_MINIMUM}</php_minimum>"
|
||||
fi
|
||||
|
||||
DOWNLOAD_URL="https://github.com/${REPO}/releases/download/v${VERSION}/${EXT_ELEMENT}-${VERSION}.zip"
|
||||
INFO_URL="https://github.com/${REPO}/releases/tag/v${VERSION}"
|
||||
DOWNLOAD_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/v${VERSION}/${EXT_ELEMENT}-${VERSION}.zip"
|
||||
INFO_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/v${VERSION}"
|
||||
|
||||
# -- Build stable entry to temp file ─────────────────────────
|
||||
{
|
||||
# -- Build update entry for a given stability tag
|
||||
build_entry() {
|
||||
local TAG_NAME="$1"
|
||||
printf '%s\n' ' <update>'
|
||||
printf '%s\n' " <name>${EXT_NAME}</name>"
|
||||
printf '%s\n' " <description>${EXT_NAME} update</description>"
|
||||
@@ -331,9 +334,7 @@ jobs:
|
||||
printf '%s\n' " <version>${VERSION}</version>"
|
||||
[ -n "$CLIENT_TAG" ] && printf '%s\n' " ${CLIENT_TAG}"
|
||||
[ -n "$FOLDER_TAG" ] && printf '%s\n' " ${FOLDER_TAG}"
|
||||
printf '%s\n' ' <tags>'
|
||||
printf '%s\n' ' <tag>stable</tag>'
|
||||
printf '%s\n' ' </tags>'
|
||||
printf '%s\n' " <tags><tag>${TAG_NAME}</tag></tags>"
|
||||
printf '%s\n' " <infourl title=\"${EXT_NAME}\">${INFO_URL}</infourl>"
|
||||
printf '%s\n' ' <downloads>'
|
||||
printf '%s\n' " <downloadurl type=\"full\" format=\"zip\">${DOWNLOAD_URL}</downloadurl>"
|
||||
@@ -343,35 +344,22 @@ jobs:
|
||||
printf '%s\n' ' <maintainer>Moko Consulting</maintainer>'
|
||||
printf '%s\n' ' <maintainerurl>https://mokoconsulting.tech</maintainerurl>'
|
||||
printf '%s\n' ' </update>'
|
||||
} > /tmp/stable_entry.xml
|
||||
|
||||
# -- Write updates.xml preserving dev/rc entries ──────────────
|
||||
# Extract existing entries for other stability levels
|
||||
# Order reflects release workflow: development → alpha → beta → rc → stable
|
||||
if [ -f "updates.xml" ]; then
|
||||
printf 'import re, sys\n' > /tmp/extract.py
|
||||
printf 'with open("updates.xml") as f: c = f.read()\n' >> /tmp/extract.py
|
||||
printf 'tag = sys.argv[1]\n' >> /tmp/extract.py
|
||||
printf 'm = re.search(r"( <update>.*?<tag>" + re.escape(tag) + r"</tag>.*?</update>)", c, re.DOTALL)\n' >> /tmp/extract.py
|
||||
printf 'if m: print(m.group(1))\n' >> /tmp/extract.py
|
||||
fi
|
||||
DEV_ENTRY=$(python3 /tmp/extract.py development 2>/dev/null || true)
|
||||
ALPHA_ENTRY=$(python3 /tmp/extract.py alpha 2>/dev/null || true)
|
||||
BETA_ENTRY=$(python3 /tmp/extract.py beta 2>/dev/null || true)
|
||||
RC_ENTRY=$(python3 /tmp/extract.py rc 2>/dev/null || true)
|
||||
}
|
||||
|
||||
# -- Write updates.xml with cascading channels
|
||||
# Stable release updates ALL channels (development, alpha, beta, rc, stable)
|
||||
{
|
||||
printf '%s\n' '<?xml version="1.0" encoding="utf-8"?>'
|
||||
printf '%s\n' '<updates>'
|
||||
[ -n "$DEV_ENTRY" ] && echo "$DEV_ENTRY"
|
||||
[ -n "$ALPHA_ENTRY" ] && echo "$ALPHA_ENTRY"
|
||||
[ -n "$BETA_ENTRY" ] && echo "$BETA_ENTRY"
|
||||
[ -n "$RC_ENTRY" ] && echo "$RC_ENTRY"
|
||||
cat /tmp/stable_entry.xml
|
||||
build_entry "development"
|
||||
build_entry "alpha"
|
||||
build_entry "beta"
|
||||
build_entry "rc"
|
||||
build_entry "stable"
|
||||
printf '%s\n' '</updates>'
|
||||
} > updates.xml
|
||||
|
||||
echo "updates.xml: ${VERSION} (stable + rc/dev preserved)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "updates.xml: ${VERSION} (all channels updated to stable)" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# -- Commit all changes ---------------------------------------------------
|
||||
- name: Commit release changes
|
||||
@@ -384,12 +372,14 @@ jobs:
|
||||
exit 0
|
||||
fi
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git config --local user.name "github-actions[bot]"
|
||||
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
||||
git config --local user.name "gitea-actions[bot]"
|
||||
# Set push URL with token for branch-protected repos
|
||||
git remote set-url origin "https://jmiller:${{ secrets.GA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
||||
git add -A
|
||||
git commit -m "chore(release): build ${VERSION} [skip ci]" \
|
||||
--author="github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
|
||||
git push
|
||||
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>"
|
||||
git push -u origin HEAD
|
||||
|
||||
# -- STEP 6: Create tag ---------------------------------------------------
|
||||
- name: "Step 6: Create git tag"
|
||||
@@ -409,69 +399,76 @@ jobs:
|
||||
fi
|
||||
echo "Tag: ${TAG}" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# -- STEP 7: Create or update GitHub Release ------------------------------
|
||||
- name: "Step 7: GitHub Release"
|
||||
# -- STEP 7: Create or update Gitea Release --------------------------------
|
||||
- name: "Step 7: Gitea Release"
|
||||
if: >-
|
||||
steps.version.outputs.skip != 'true' &&
|
||||
steps.check.outputs.tag_exists != 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
|
||||
run: |
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
|
||||
BRANCH="${{ steps.version.outputs.branch }}"
|
||||
MAJOR="${{ steps.version.outputs.major }}"
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
|
||||
NOTES=$(php /tmp/mokostandards/api/cli/release_notes.php --path . --version "$VERSION" 2>/dev/null)
|
||||
NOTES=$(php /tmp/mokostandards-api/cli/release_notes.php --path . --version "$VERSION" 2>/dev/null)
|
||||
[ -z "$NOTES" ] && NOTES="Release ${VERSION}"
|
||||
echo "$NOTES" > /tmp/release_notes.md
|
||||
|
||||
# Check if the major release already exists
|
||||
EXISTING=$(gh release view "$RELEASE_TAG" --json tagName -q .tagName 2>/dev/null || true)
|
||||
EXISTING=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
||||
"${API_BASE}/releases/tags/${RELEASE_TAG}" 2>/dev/null || true)
|
||||
EXISTING_ID=$(echo "$EXISTING" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('id',''))" 2>/dev/null || true)
|
||||
|
||||
if [ -z "$EXISTING" ]; then
|
||||
if [ -z "$EXISTING_ID" ]; then
|
||||
# First release for this major
|
||||
gh release create "$RELEASE_TAG" \
|
||||
--title "v${MAJOR} (latest: ${VERSION})" \
|
||||
--notes-file /tmp/release_notes.md \
|
||||
--target "$BRANCH"
|
||||
curl -sf -X POST -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API_BASE}/releases" \
|
||||
-d "$(python3 -c "import json; print(json.dumps({
|
||||
'tag_name': '${RELEASE_TAG}',
|
||||
'name': 'v${MAJOR} (latest: ${VERSION})',
|
||||
'body': '''${NOTES}''',
|
||||
'target_commitish': '${BRANCH}'
|
||||
}))")"
|
||||
echo "Release created: ${RELEASE_TAG} (${VERSION})" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
# Append version notes to existing major release
|
||||
CURRENT_NOTES=$(gh release view "$RELEASE_TAG" --json body -q .body 2>/dev/null || true)
|
||||
{
|
||||
echo "$CURRENT_NOTES"
|
||||
echo ""
|
||||
echo "---"
|
||||
echo "### ${VERSION}"
|
||||
echo ""
|
||||
cat /tmp/release_notes.md
|
||||
} > /tmp/updated_notes.md
|
||||
CURRENT_BODY=$(echo "$EXISTING" | python3 -c "import sys,json; print(json.load(sys.stdin).get('body',''))" 2>/dev/null || true)
|
||||
UPDATED_BODY="${CURRENT_BODY}
|
||||
|
||||
gh release edit "$RELEASE_TAG" \
|
||||
--title "v${MAJOR} (latest: ${VERSION})" \
|
||||
--notes-file /tmp/updated_notes.md
|
||||
---
|
||||
### ${VERSION}
|
||||
|
||||
${NOTES}"
|
||||
|
||||
curl -sf -X PATCH -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API_BASE}/releases/${EXISTING_ID}" \
|
||||
-d "$(python3 -c "import json,sys; print(json.dumps({
|
||||
'name': 'v${MAJOR} (latest: ${VERSION})',
|
||||
'body': sys.stdin.read()
|
||||
}))" <<< "$UPDATED_BODY")"
|
||||
echo "Release updated: ${RELEASE_TAG} -> ${VERSION}" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
# -- STEP 8: Build Joomla install ZIP + SHA-256 checksum ------------------
|
||||
# Every patch builds an install-ready ZIP and uploads it to the minor release.
|
||||
# Result: one Release per minor version with a ZIP for each patch.
|
||||
- name: "Step 8: Build Joomla package and update checksum"
|
||||
if: >-
|
||||
steps.version.outputs.skip != 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
|
||||
run: |
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
|
||||
REPO="${{ github.repository }}"
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
|
||||
# All ZIPs upload to the major release tag (vXX)
|
||||
gh release view "$RELEASE_TAG" --json tagName > /dev/null 2>&1 || {
|
||||
RELEASE_JSON=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
||||
"${API_BASE}/releases/tags/${RELEASE_TAG}" 2>/dev/null || true)
|
||||
RELEASE_ID=$(echo "$RELEASE_JSON" | python3 -c "import sys,json; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
|
||||
if [ -z "$RELEASE_ID" ]; then
|
||||
echo "No release ${RELEASE_TAG} found — skipping ZIP upload"
|
||||
exit 0
|
||||
}
|
||||
fi
|
||||
|
||||
# Find extension element name from manifest
|
||||
MANIFEST=$(find . -maxdepth 2 -name "*.xml" -exec grep -l '<extension' {} \; 2>/dev/null | head -1 || true)
|
||||
@@ -505,27 +502,108 @@ jobs:
|
||||
SHA256_ZIP=$(sha256sum "/tmp/${ZIP_NAME}" | cut -d' ' -f1)
|
||||
SHA256_TAR=$(sha256sum "/tmp/${TAR_NAME}" | cut -d' ' -f1)
|
||||
|
||||
# -- Delete existing assets with same name before uploading ------
|
||||
ASSETS=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
||||
"${API_BASE}/releases/${RELEASE_ID}/assets" 2>/dev/null || echo "[]")
|
||||
for ASSET_NAME in "$ZIP_NAME" "$TAR_NAME"; do
|
||||
ASSET_ID=$(echo "$ASSETS" | python3 -c "
|
||||
import sys,json
|
||||
assets = json.load(sys.stdin)
|
||||
for a in assets:
|
||||
if a['name'] == '${ASSET_NAME}':
|
||||
print(a['id']); break
|
||||
" 2>/dev/null || true)
|
||||
if [ -n "$ASSET_ID" ]; then
|
||||
curl -sf -X DELETE -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
||||
"${API_BASE}/releases/${RELEASE_ID}/assets/${ASSET_ID}" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
|
||||
# -- Upload both to release tag ----------------------------------
|
||||
gh release upload "$RELEASE_TAG" "/tmp/${ZIP_NAME}" --clobber 2>/dev/null || true
|
||||
gh release upload "$RELEASE_TAG" "/tmp/${TAR_NAME}" --clobber 2>/dev/null || true
|
||||
curl -sf -X POST -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
--data-binary @"/tmp/${ZIP_NAME}" \
|
||||
"${API_BASE}/releases/${RELEASE_ID}/assets?name=${ZIP_NAME}" > /dev/null 2>&1 || true
|
||||
|
||||
curl -sf -X POST -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
--data-binary @"/tmp/${TAR_NAME}" \
|
||||
"${API_BASE}/releases/${RELEASE_ID}/assets?name=${TAR_NAME}" > /dev/null 2>&1 || true
|
||||
|
||||
# -- Update updates.xml with both download formats ---------------
|
||||
if [ -f "updates.xml" ]; then
|
||||
ZIP_URL="https://github.com/${REPO}/releases/download/${RELEASE_TAG}/${ZIP_NAME}"
|
||||
TAR_URL="https://github.com/${REPO}/releases/download/${RELEASE_TAG}/${TAR_NAME}"
|
||||
ZIP_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/${RELEASE_TAG}/${ZIP_NAME}"
|
||||
TAR_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/${RELEASE_TAG}/${TAR_NAME}"
|
||||
|
||||
# Replace downloads block with both formats + SHA
|
||||
sed -i "s|<downloads>.*</downloads>|<downloads>\n <downloadurl type=\"full\" format=\"zip\">${ZIP_URL}</downloadurl>\n <downloadurl type=\"full\" format=\"tar.gz\">${TAR_URL}</downloadurl>\n </downloads>|" updates.xml 2>/dev/null || true
|
||||
if grep -q '<sha256>' updates.xml; then
|
||||
sed -i "s|<sha256>.*</sha256>|<sha256>sha256:${SHA256_ZIP}</sha256>|" updates.xml
|
||||
else
|
||||
sed -i "s|</downloads>|</downloads>\n <sha256>sha256:${SHA256_ZIP}</sha256>|" updates.xml
|
||||
fi
|
||||
# Use Python to update only the stable entry's downloads + sha256
|
||||
export PY_ZIP_URL="$ZIP_URL" PY_TAR_URL="$TAR_URL" PY_SHA="$SHA256_ZIP"
|
||||
python3 << 'PYEOF'
|
||||
import re, os
|
||||
|
||||
with open("updates.xml") as f:
|
||||
content = f.read()
|
||||
|
||||
zip_url = os.environ["PY_ZIP_URL"]
|
||||
tar_url = os.environ["PY_TAR_URL"]
|
||||
sha = os.environ["PY_SHA"]
|
||||
|
||||
# Find the stable update block and replace its downloads + sha256
|
||||
def replace_stable(m):
|
||||
block = m.group(0)
|
||||
# Replace downloads block
|
||||
new_downloads = (
|
||||
" <downloads>\n"
|
||||
f" <downloadurl type=\"full\" format=\"zip\">{zip_url}</downloadurl>\n"
|
||||
f" <downloadurl type=\"full\" format=\"tar.gz\">{tar_url}</downloadurl>\n"
|
||||
" </downloads>"
|
||||
)
|
||||
block = re.sub(r' <downloads>.*?</downloads>', new_downloads, block, flags=re.DOTALL)
|
||||
# Add or replace sha256
|
||||
if '<sha256>' in block:
|
||||
block = re.sub(r' <sha256>.*?</sha256>', f' <sha256>{sha}</sha256>', block)
|
||||
else:
|
||||
block = block.replace('</downloads>', f'</downloads>\n <sha256>{sha}</sha256>')
|
||||
return block
|
||||
|
||||
content = re.sub(
|
||||
r' <update>.*?<tag>stable</tag>.*?</update>',
|
||||
replace_stable,
|
||||
content,
|
||||
flags=re.DOTALL
|
||||
)
|
||||
|
||||
with open("updates.xml", "w") as f:
|
||||
f.write(content)
|
||||
PYEOF
|
||||
|
||||
CURRENT_BRANCH="${{ github.ref_name }}"
|
||||
git add updates.xml
|
||||
git commit -m "chore(release): ZIP + tar.gz for ${VERSION} [skip ci]" \
|
||||
--author="github-actions[bot] <github-actions[bot]@users.noreply.github.com>" || true
|
||||
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>" || true
|
||||
git push || true
|
||||
|
||||
# Also update updates.xml on main via Gitea API (git push blocked by branch protection)
|
||||
if [ "$CURRENT_BRANCH" != "main" ]; then
|
||||
GA_TOKEN="${{ secrets.GA_TOKEN }}"
|
||||
API="${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}"
|
||||
|
||||
FILE_SHA=$(curl -sf -H "Authorization: token ${GA_TOKEN}" \
|
||||
"${API}/contents/updates.xml?ref=main" | jq -r '.sha // empty')
|
||||
|
||||
if [ -n "$FILE_SHA" ]; then
|
||||
CONTENT=$(base64 -w0 updates.xml)
|
||||
curl -sf -X PUT -H "Authorization: token ${GA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API}/contents/updates.xml" \
|
||||
-d "$(jq -n \
|
||||
--arg content "$CONTENT" \
|
||||
--arg sha "$FILE_SHA" \
|
||||
--arg msg "chore: update stable channel to ${VERSION} on main [skip ci]" \
|
||||
--arg branch "main" \
|
||||
'{content: $content, sha: $sha, message: $msg, branch: $branch}'
|
||||
)" > /dev/null && echo "updates.xml synced to main via API" || echo "WARNING: failed to sync updates.xml to main"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "### Joomla Packages" >> $GITHUB_STEP_SUMMARY
|
||||
@@ -535,7 +613,50 @@ jobs:
|
||||
echo "| \`${ZIP_NAME}\` | ${ZIP_SIZE} | \`${SHA256_ZIP}\` |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| \`${TAR_NAME}\` | ${TAR_SIZE} | \`${SHA256_TAR}\` |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Release | \`${RELEASE_TAG}\` | |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Download | [${PACKAGE_NAME}](https://github.com/${REPO}/releases/download/${RELEASE_TAG}/${PACKAGE_NAME}) |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Download | [${ZIP_NAME}](${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/${RELEASE_TAG}/${ZIP_NAME}) |" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# -- STEP 9: Mirror to GitHub (stable only) --------------------------------
|
||||
- name: "Step 9: Mirror release to GitHub"
|
||||
if: >-
|
||||
steps.version.outputs.skip != 'true' &&
|
||||
steps.version.outputs.stability == 'stable' &&
|
||||
secrets.GH_TOKEN != ''
|
||||
continue-on-error: true
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
run: |
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
|
||||
MAJOR="${{ steps.version.outputs.major }}"
|
||||
BRANCH="${{ steps.version.outputs.branch }}"
|
||||
GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
|
||||
|
||||
NOTES=$(php /tmp/mokostandards-api/cli/release_notes.php --path . --version "$VERSION" 2>/dev/null || true)
|
||||
[ -z "$NOTES" ] && NOTES="Release ${VERSION}"
|
||||
echo "$NOTES" > /tmp/release_notes.md
|
||||
|
||||
EXISTING=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}/releases/tags/$RELEASE_TAG" 2>/dev/null | jq -r ".tag_name // empty" || true)
|
||||
|
||||
if [ -z "$EXISTING" ]; then
|
||||
gh release create "$RELEASE_TAG" \
|
||||
--repo "$GH_REPO" \
|
||||
--title "v${MAJOR} (latest: ${VERSION})" \
|
||||
--notes-file /tmp/release_notes.md \
|
||||
--target "$BRANCH" || true
|
||||
else
|
||||
gh release edit "$RELEASE_TAG" \
|
||||
--repo "$GH_REPO" \
|
||||
--title "v${MAJOR} (latest: ${VERSION})" || true
|
||||
fi
|
||||
|
||||
# Upload assets to GitHub mirror
|
||||
for PKG in /tmp/${EXT_ELEMENT:-pkg}-${VERSION}.*; do
|
||||
if [ -f "$PKG" ]; then
|
||||
_RELID=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}/releases/tags/$RELEASE_TAG" 2>/dev/null | jq -r ".id // empty")
|
||||
[ -n "$_RELID" ] && curl -sf -X POST -H "Authorization: token ${{ secrets.GA_TOKEN }}" -H "Content-Type: application/octet-stream" "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}/releases/${_RELID}/assets?name=$(basename $PKG)" --data-binary "@$PKG" > /dev/null 2>&1 || true
|
||||
fi
|
||||
done
|
||||
echo "GitHub mirror updated: ${GH_REPO} ${RELEASE_TAG}" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# -- Summary --------------------------------------------------------------
|
||||
- name: Pipeline Summary
|
||||
@@ -556,5 +677,5 @@ jobs:
|
||||
echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Branch | \`${{ steps.version.outputs.branch }}\` |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Tag | \`${{ steps.version.outputs.tag }}\` |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Release | [View](https://github.com/${{ github.repository }}/releases/tag/${{ steps.version.outputs.tag }}) |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Release | [View](${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/${{ steps.version.outputs.tag }}) |" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: GitHub.Workflow
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: MokoStandards.Joomla
|
||||
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
|
||||
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API
|
||||
# PATH: /templates/workflows/joomla/update-server.yml.template
|
||||
# VERSION: 04.06.00
|
||||
# BRIEF: Update Joomla update server XML feed with stable/rc/dev entries
|
||||
@@ -46,6 +46,9 @@ on:
|
||||
|
||||
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
|
||||
@@ -61,39 +64,40 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
with:
|
||||
token: ${{ secrets.GH_TOKEN || github.token }}
|
||||
token: ${{ secrets.GA_TOKEN }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup MokoStandards tools
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
|
||||
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
|
||||
MOKO_CLONE_TOKEN: ${{ secrets.GA_TOKEN }}
|
||||
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
||||
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN }}"}}'
|
||||
run: |
|
||||
git clone --depth 1 --branch version/04 --quiet \
|
||||
"https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \
|
||||
/tmp/mokostandards 2>/dev/null || true
|
||||
if [ -d "/tmp/mokostandards" ] && [ -f "/tmp/mokostandards/composer.json" ]; then
|
||||
cd /tmp/mokostandards && composer install --no-dev --no-interaction --quiet 2>/dev/null || true
|
||||
git clone --depth 1 --branch main --quiet \
|
||||
"https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoStandards-API.git" \
|
||||
/tmp/mokostandards-api 2>/dev/null || true
|
||||
if [ -d "/tmp/mokostandards-api" ] && [ -f "/tmp/mokostandards-api/composer.json" ]; then
|
||||
cd /tmp/mokostandards-api && composer install --no-dev --no-interaction --quiet 2>/dev/null || true
|
||||
fi
|
||||
|
||||
- name: Generate updates.xml entry
|
||||
id: update
|
||||
run: |
|
||||
BRANCH="${{ github.ref_name }}"
|
||||
REPO="${{ github.repository }}"
|
||||
VERSION=$(php /tmp/mokostandards/api/cli/version_read.php --path . 2>/dev/null || echo "0.0.0")
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
VERSION=$(php /tmp/mokostandards-api/cli/version_read.php --path . 2>/dev/null || echo "0.0.0")
|
||||
|
||||
# Auto-bump patch on alpha/beta/rc branches (not dev — dev bumps manually)
|
||||
if [[ "$BRANCH" != dev/* ]]; then
|
||||
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git config --local user.name "github-actions[bot]"
|
||||
BUMPED=$(php /tmp/mokostandards/api/cli/version_bump.php --path . 2>/dev/null || true)
|
||||
if [ -n "$BUMPED" ]; then
|
||||
VERSION=$(php /tmp/mokostandards/api/cli/version_read.php --path . 2>/dev/null || echo "$VERSION")
|
||||
git add -A
|
||||
git commit -m "chore(version): auto-bump patch ${VERSION} [skip ci]" \
|
||||
--author="github-actions[bot] <github-actions[bot]@users.noreply.github.com>" 2>/dev/null || true
|
||||
git push 2>/dev/null || true
|
||||
fi
|
||||
# Auto-bump patch on all branches (dev, alpha, beta, rc)
|
||||
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
||||
git config --local user.name "gitea-actions[bot]"
|
||||
BUMPED=$(php /tmp/mokostandards-api/cli/version_bump.php --path . 2>/dev/null || true)
|
||||
if [ -n "$BUMPED" ]; then
|
||||
VERSION=$(php /tmp/mokostandards-api/cli/version_read.php --path . 2>/dev/null || echo "$VERSION")
|
||||
git add -A
|
||||
git commit -m "chore(version): auto-bump patch ${VERSION} [skip ci]" \
|
||||
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>" 2>/dev/null || true
|
||||
git push 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Determine stability from branch or input
|
||||
@@ -111,6 +115,8 @@ jobs:
|
||||
STABILITY="stable"
|
||||
fi
|
||||
|
||||
echo "stability=${STABILITY}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Parse manifest (portable — no grep -P)
|
||||
MANIFEST=$(find . -maxdepth 2 -name "*.xml" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
|
||||
if [ -z "$MANIFEST" ]; then
|
||||
@@ -140,7 +146,7 @@ jobs:
|
||||
# Use manifest version if README version is empty
|
||||
[ "$VERSION" = "0.0.0" ] && [ -n "$EXT_VERSION" ] && VERSION="$EXT_VERSION"
|
||||
|
||||
[ -z "$TARGET_PLATFORM" ] && TARGET_PLATFORM=$(printf '<targetplatform name="joomla" version="5.*" %s>' "/")
|
||||
[ -z "$TARGET_PLATFORM" ] && TARGET_PLATFORM=$(printf '<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" %s>' "/")
|
||||
|
||||
CLIENT_TAG=""
|
||||
[ -n "$EXT_CLIENT" ] && CLIENT_TAG="<client>${EXT_CLIENT}</client>"
|
||||
@@ -173,10 +179,10 @@ jobs:
|
||||
esac
|
||||
|
||||
PACKAGE_NAME="${EXT_ELEMENT}-${DISPLAY_VERSION}.zip"
|
||||
DOWNLOAD_URL="https://github.com/${REPO}/releases/download/${RELEASE_TAG}/${PACKAGE_NAME}"
|
||||
INFO_URL="https://github.com/${REPO}"
|
||||
DOWNLOAD_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/${RELEASE_TAG}/${PACKAGE_NAME}"
|
||||
INFO_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}"
|
||||
|
||||
# ── Build install packages (ZIP + tar.gz) ───────────────────
|
||||
# -- Build install packages (ZIP + tar.gz) --------------------
|
||||
SOURCE_DIR="src"
|
||||
[ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs"
|
||||
if [ -d "$SOURCE_DIR" ]; then
|
||||
@@ -192,20 +198,62 @@ jobs:
|
||||
|
||||
SHA256=$(sha256sum "/tmp/${PACKAGE_NAME}" | cut -d' ' -f1)
|
||||
|
||||
# Ensure release exists
|
||||
gh release view "$RELEASE_TAG" --json tagName > /dev/null 2>&1 || \
|
||||
gh release create "$RELEASE_TAG" --title "${RELEASE_TAG} (${DISPLAY_VERSION})" --notes "${STABILITY} release" --prerelease --target main 2>/dev/null || true
|
||||
# Ensure release exists on Gitea
|
||||
RELEASE_JSON=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
||||
"${API_BASE}/releases/tags/${RELEASE_TAG}" 2>/dev/null || true)
|
||||
RELEASE_ID=$(echo "$RELEASE_JSON" | python3 -c "import sys,json; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
|
||||
|
||||
# Upload both formats
|
||||
gh release upload "$RELEASE_TAG" "/tmp/${PACKAGE_NAME}" --clobber 2>/dev/null || true
|
||||
gh release upload "$RELEASE_TAG" "/tmp/${TAR_NAME}" --clobber 2>/dev/null || true
|
||||
if [ -z "$RELEASE_ID" ]; then
|
||||
# Create release
|
||||
RELEASE_JSON=$(curl -sf -X POST -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API_BASE}/releases" \
|
||||
-d "$(python3 -c "import json; print(json.dumps({
|
||||
'tag_name': '${RELEASE_TAG}',
|
||||
'name': '${RELEASE_TAG} (${DISPLAY_VERSION})',
|
||||
'body': '${STABILITY} release',
|
||||
'prerelease': True,
|
||||
'target_commitish': 'main'
|
||||
}))")" 2>/dev/null || true)
|
||||
RELEASE_ID=$(echo "$RELEASE_JSON" | python3 -c "import sys,json; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
|
||||
fi
|
||||
|
||||
if [ -n "$RELEASE_ID" ]; then
|
||||
# Delete existing assets with same name before uploading
|
||||
ASSETS=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
||||
"${API_BASE}/releases/${RELEASE_ID}/assets" 2>/dev/null || echo "[]")
|
||||
for ASSET_FILE in "$PACKAGE_NAME" "$TAR_NAME"; do
|
||||
ASSET_ID=$(echo "$ASSETS" | python3 -c "
|
||||
import sys,json
|
||||
assets = json.load(sys.stdin)
|
||||
for a in assets:
|
||||
if a['name'] == '${ASSET_FILE}':
|
||||
print(a['id']); break
|
||||
" 2>/dev/null || true)
|
||||
if [ -n "$ASSET_ID" ]; then
|
||||
curl -sf -X DELETE -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
||||
"${API_BASE}/releases/${RELEASE_ID}/assets/${ASSET_ID}" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
|
||||
# Upload both formats
|
||||
curl -sf -X POST -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
--data-binary @"/tmp/${PACKAGE_NAME}" \
|
||||
"${API_BASE}/releases/${RELEASE_ID}/assets?name=${PACKAGE_NAME}" > /dev/null 2>&1 || true
|
||||
|
||||
curl -sf -X POST -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
--data-binary @"/tmp/${TAR_NAME}" \
|
||||
"${API_BASE}/releases/${RELEASE_ID}/assets?name=${TAR_NAME}" > /dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
echo "Packages: ${PACKAGE_NAME} + ${TAR_NAME} (SHA: ${SHA256})" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
SHA256=""
|
||||
fi
|
||||
|
||||
# ── Build the new entry ───────────────────────────────────────
|
||||
# -- Build the new entry -----------------------------------------
|
||||
NEW_ENTRY=""
|
||||
NEW_ENTRY="${NEW_ENTRY} <update>\n"
|
||||
NEW_ENTRY="${NEW_ENTRY} <name>${EXT_NAME}</name>\n"
|
||||
@@ -220,37 +268,65 @@ jobs:
|
||||
NEW_ENTRY="${NEW_ENTRY} </tags>\n"
|
||||
NEW_ENTRY="${NEW_ENTRY} <infourl title=\"${EXT_NAME}\">${INFO_URL}</infourl>\n"
|
||||
NEW_ENTRY="${NEW_ENTRY} <downloads>\n"
|
||||
TAR_URL="https://github.com/${REPO}/releases/download/${RELEASE_TAG}/${EXT_ELEMENT}-${DISPLAY_VERSION}.tar.gz"
|
||||
TAR_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/${RELEASE_TAG}/${EXT_ELEMENT}-${DISPLAY_VERSION}.tar.gz"
|
||||
NEW_ENTRY="${NEW_ENTRY} <downloadurl type=\"full\" format=\"zip\">${DOWNLOAD_URL}</downloadurl>\n"
|
||||
NEW_ENTRY="${NEW_ENTRY} <downloadurl type=\"full\" format=\"tar.gz\">${TAR_URL}</downloadurl>\n"
|
||||
NEW_ENTRY="${NEW_ENTRY} </downloads>\n"
|
||||
[ -n "$SHA256" ] && NEW_ENTRY="${NEW_ENTRY} <sha256>sha256:${SHA256}</sha256>\n"
|
||||
[ -n "$SHA256" ] && NEW_ENTRY="${NEW_ENTRY} <sha256>${SHA256}</sha256>\n"
|
||||
NEW_ENTRY="${NEW_ENTRY} ${TARGET_PLATFORM}\n"
|
||||
[ -n "$PHP_TAG" ] && NEW_ENTRY="${NEW_ENTRY} ${PHP_TAG}\n"
|
||||
NEW_ENTRY="${NEW_ENTRY} <maintainer>Moko Consulting</maintainer>\n"
|
||||
NEW_ENTRY="${NEW_ENTRY} <maintainerurl>https://mokoconsulting.tech</maintainerurl>\n"
|
||||
NEW_ENTRY="${NEW_ENTRY} </update>"
|
||||
|
||||
# ── Write new entry to temp file ───────────────────────────────
|
||||
# -- Write new entry to temp file --------------------------------
|
||||
printf '%b' "$NEW_ENTRY" > /tmp/new_entry.xml
|
||||
|
||||
# ── Merge into updates.xml ─────────────────────────────────────
|
||||
# -- Merge into updates.xml (only update this stability channel) -
|
||||
# Cascading update: each stability level updates itself and all lower levels
|
||||
# stable → all | rc → rc,beta,alpha,dev | beta → beta,alpha,dev | alpha → alpha,dev | dev → dev
|
||||
CASCADE_MAP="stable:development,alpha,beta,rc,stable rc:development,alpha,beta,rc beta:development,alpha,beta alpha:development,alpha development:development"
|
||||
TARGETS=""
|
||||
for entry in $CASCADE_MAP; do
|
||||
key="${entry%%:*}"
|
||||
vals="${entry#*:}"
|
||||
if [ "$key" = "${STABILITY}" ]; then
|
||||
TARGETS="$vals"
|
||||
break
|
||||
fi
|
||||
done
|
||||
[ -z "$TARGETS" ] && TARGETS="${STABILITY}"
|
||||
|
||||
if [ ! -f "updates.xml" ]; then
|
||||
printf '%s\n' '<?xml version="1.0" encoding="utf-8"?>' > updates.xml
|
||||
printf '%s\n' '<updates>' >> updates.xml
|
||||
cat /tmp/new_entry.xml >> updates.xml
|
||||
printf '\n%s\n' '</updates>' >> updates.xml
|
||||
else
|
||||
# Remove existing entry for this stability, insert new one
|
||||
printf 'import re\nstability = "%s"\n' "${STABILITY}" > /tmp/merge_xml.py
|
||||
printf 'with open("updates.xml") as f: content = f.read()\n' >> /tmp/merge_xml.py
|
||||
printf 'with open("/tmp/new_entry.xml") as f: new_entry = f.read()\n' >> /tmp/merge_xml.py
|
||||
printf 'pattern = r" <update>.*?<tag>" + re.escape(stability) + r"</tag>.*?</update>\\n?"\n' >> /tmp/merge_xml.py
|
||||
printf 'content = re.sub(pattern, "", content, flags=re.DOTALL)\n' >> /tmp/merge_xml.py
|
||||
printf 'content = content.replace("</updates>", new_entry + "\\n</updates>")\n' >> /tmp/merge_xml.py
|
||||
printf 'content = re.sub(r"\\n{3,}", "\\n\\n", content)\n' >> /tmp/merge_xml.py
|
||||
printf 'with open("updates.xml", "w") as f: f.write(content)\n' >> /tmp/merge_xml.py
|
||||
python3 /tmp/merge_xml.py 2>/dev/null || {
|
||||
# Replace each cascading channel with the new entry (different tag)
|
||||
export PY_TARGETS="$TARGETS"
|
||||
python3 << PYEOF
|
||||
import re, os
|
||||
targets = os.environ["PY_TARGETS"].split(",")
|
||||
stability = "${STABILITY}"
|
||||
with open("updates.xml") as f:
|
||||
content = f.read()
|
||||
with open("/tmp/new_entry.xml") as f:
|
||||
new_entry_template = f.read()
|
||||
for tag in targets:
|
||||
tag = tag.strip()
|
||||
# Build entry with this tag
|
||||
new_entry = re.sub(r"<tag>[^<]*</tag>", f"<tag>{tag}</tag>", new_entry_template)
|
||||
# Remove existing entry for this tag
|
||||
pattern = r" <update>.*?<tag>" + re.escape(tag) + r"</tag>.*?</update>\n?"
|
||||
content = re.sub(pattern, "", content, flags=re.DOTALL)
|
||||
# Insert before </updates>
|
||||
content = content.replace("</updates>", new_entry + "\n</updates>")
|
||||
content = re.sub(r"\n{3,}", "\n\n", content)
|
||||
with open("updates.xml", "w") as f:
|
||||
f.write(content)
|
||||
PYEOF
|
||||
if [ $? -ne 0 ]; then
|
||||
# Fallback: rebuild keeping other stability entries
|
||||
{
|
||||
printf '%s\n' '<?xml version="1.0" encoding="utf-8"?>'
|
||||
@@ -265,19 +341,39 @@ jobs:
|
||||
printf '\n%s\n' '</updates>'
|
||||
} > /tmp/updates_new.xml
|
||||
mv /tmp/updates_new.xml updates.xml
|
||||
}
|
||||
fi
|
||||
fi
|
||||
|
||||
# Commit
|
||||
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git config --local user.name "github-actions[bot]"
|
||||
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
||||
git config --local user.name "gitea-actions[bot]"
|
||||
git add updates.xml
|
||||
git diff --cached --quiet || {
|
||||
git commit -m "chore: update updates.xml (${STABILITY}: ${DISPLAY_VERSION}) [skip ci]" \
|
||||
--author="github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
|
||||
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>"
|
||||
git push
|
||||
}
|
||||
|
||||
# -- Mirror to GitHub (stable and rc only) --------------------------------
|
||||
- name: Mirror release to GitHub
|
||||
if: >-
|
||||
(steps.update.outputs.stability == 'stable' || steps.update.outputs.stability == 'rc') &&
|
||||
secrets.GH_TOKEN != ''
|
||||
continue-on-error: true
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
run: |
|
||||
GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
|
||||
STABILITY="${{ steps.update.outputs.stability }}"
|
||||
echo "GitHub mirror sync for ${STABILITY} — ${GH_REPO}" >> $GITHUB_STEP_SUMMARY
|
||||
# Mirror packages if they exist
|
||||
for PKG in /tmp/*.zip /tmp/*.tar.gz; do
|
||||
if [ -f "$PKG" ]; then
|
||||
_RELID=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}/releases/tags/${RELEASE_TAG}" 2>/dev/null | jq -r ".id // empty")
|
||||
[ -n "$_RELID" ] && curl -sf -X POST -H "Authorization: token ${{ secrets.GA_TOKEN }}" -H "Content-Type: application/octet-stream" "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}/releases/${_RELID}/assets?name=$(basename $PKG)" --data-binary "@$PKG" > /dev/null 2>&1 || true
|
||||
fi
|
||||
done
|
||||
|
||||
- name: SFTP deploy to dev server
|
||||
if: contains(github.ref, 'dev/')
|
||||
env:
|
||||
@@ -288,15 +384,15 @@ jobs:
|
||||
DEV_PORT: ${{ vars.DEV_FTP_PORT }}
|
||||
DEV_KEY: ${{ secrets.DEV_FTP_KEY }}
|
||||
DEV_PASS: ${{ secrets.DEV_FTP_PASSWORD }}
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
|
||||
run: |
|
||||
# ── Permission check: admin or maintain role required ──────
|
||||
# -- Permission check: admin or maintain role required --------
|
||||
ACTOR="${{ github.actor }}"
|
||||
REPO="${{ github.repository }}"
|
||||
PERMISSION=$(gh api "repos/${REPO}/collaborators/${ACTOR}/permission" \
|
||||
--jq '.permission' 2>/dev/null || \
|
||||
gh api "repos/${REPO}/collaborators/${ACTOR}" \
|
||||
--jq '.role' 2>/dev/null || echo "read")
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
|
||||
PERMISSION=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
||||
"${API_BASE}/collaborators/${ACTOR}/permission" 2>/dev/null | \
|
||||
python3 -c "import sys,json; print(json.load(sys.stdin).get('permission','read'))" 2>/dev/null || echo "read")
|
||||
case "$PERMISSION" in
|
||||
admin|maintain|write) ;;
|
||||
*)
|
||||
@@ -324,11 +420,11 @@ jobs:
|
||||
printf ',"password":"%s"}' "$DEV_PASS" >> /tmp/sftp-config.json
|
||||
fi
|
||||
|
||||
PLATFORM=$(php /tmp/mokostandards/api/cli/platform_detect.php --path . 2>/dev/null || true)
|
||||
if [ "$PLATFORM" = "waas-component" ] && [ -f "/tmp/mokostandards/api/deploy/deploy-joomla.php" ]; then
|
||||
php /tmp/mokostandards/api/deploy/deploy-joomla.php --path . --src-dir "$SOURCE_DIR" --config /tmp/sftp-config.json
|
||||
elif [ -f "/tmp/mokostandards/api/deploy/deploy-sftp.php" ]; then
|
||||
php /tmp/mokostandards/api/deploy/deploy-sftp.php --path . --src-dir "$SOURCE_DIR" --config /tmp/sftp-config.json
|
||||
PLATFORM=$(php /tmp/mokostandards-api/cli/platform_detect.php --path . 2>/dev/null || true)
|
||||
if [ "$PLATFORM" = "waas-component" ] && [ -f "/tmp/mokostandards-api/deploy/deploy-joomla.php" ]; then
|
||||
php /tmp/mokostandards-api/deploy/deploy-joomla.php --path . --src-dir "$SOURCE_DIR" --config /tmp/sftp-config.json
|
||||
elif [ -f "/tmp/mokostandards-api/deploy/deploy-sftp.php" ]; then
|
||||
php /tmp/mokostandards-api/deploy/deploy-sftp.php --path . --src-dir "$SOURCE_DIR" --config /tmp/sftp-config.json
|
||||
fi
|
||||
rm -f /tmp/deploy_key /tmp/sftp-config.json
|
||||
echo "SFTP deploy to dev complete" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
DEFGROUP: Joomla.Plugin
|
||||
INGROUP: MokoWaaS
|
||||
REPO: https://github.com/mokoconsulting-tech/mokowaas
|
||||
VERSION: 02.01.13
|
||||
VERSION: 02.01.14
|
||||
PATH: /README.md
|
||||
BRIEF: Rebranding plugin for MokoWaaS platform
|
||||
NOTE: Internal WaaS identity abstraction layer
|
||||
|
||||
+3
-2
@@ -29,14 +29,15 @@
|
||||
<license>GNU General Public License version 3 or later; see LICENSE.md</license>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||
<version>02.01.11</version>
|
||||
<version>02.01.14</version>
|
||||
<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>
|
||||
<scriptfile>script.php</scriptfile>
|
||||
|
||||
<!-- Update server configuration -->
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="MokoWaaS Update Server">https://raw.githubusercontent.com/mokoconsulting-tech/MokoWaaS/main/updates.xml</server>
|
||||
<server type="extension" priority="1" name="MokoWaaS Update Server (GitHub)">https://raw.githubusercontent.com/mokoconsulting-tech/MokoWaaS/main/updates.xml</server>
|
||||
<server type="extension" priority="2" name="MokoWaaS Update Server (Gitea)">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/raw/branch/main/updates.xml</server>
|
||||
</updateservers>
|
||||
|
||||
<files>
|
||||
|
||||
+44
-11
@@ -210,10 +210,11 @@ class plgSystemMokoWaaSInstallerScript implements InstallerScriptInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure mokocassiopeia template is installed and locked.
|
||||
* Ensure the active Moko template is installed and locked.
|
||||
*
|
||||
* If the template exists in #__extensions, lock and protect it.
|
||||
* If not found, attempt to install from the update server.
|
||||
* Prefers MokoOnyx (successor). Falls back to MokoCassiopeia.
|
||||
* If MokoOnyx is found, lock it and unlock MokoCassiopeia.
|
||||
* If only MokoCassiopeia is found, lock it as before.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
@@ -221,17 +222,50 @@ class plgSystemMokoWaaSInstallerScript implements InstallerScriptInterface
|
||||
*/
|
||||
private function ensureMokoCassiopeia()
|
||||
{
|
||||
$db = Factory::getDbo();
|
||||
$db = Factory::getDbo();
|
||||
|
||||
// Check for MokoOnyx first (successor template)
|
||||
$query = $db->getQuery(true)
|
||||
->select([$db->quoteName('extension_id'), $db->quoteName('enabled')])
|
||||
->from($db->quoteName('#__extensions'))
|
||||
->where($db->quoteName('element') . ' = '
|
||||
. $db->quote('mokocassiopeia'))
|
||||
->where($db->quoteName('type') . ' = '
|
||||
. $db->quote('template'));
|
||||
->where($db->quoteName('element') . ' = ' . $db->quote('mokoonyx'))
|
||||
->where($db->quoteName('type') . ' = ' . $db->quote('template'));
|
||||
$onyx = $db->setQuery($query)->loadObject();
|
||||
|
||||
$db->setQuery($query);
|
||||
$template = $db->loadObject();
|
||||
if ($onyx)
|
||||
{
|
||||
// Lock and protect MokoOnyx
|
||||
$db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->update($db->quoteName('#__extensions'))
|
||||
->set($db->quoteName('enabled') . ' = 1')
|
||||
->set($db->quoteName('locked') . ' = 1')
|
||||
->set($db->quoteName('protected') . ' = 1')
|
||||
->where($db->quoteName('extension_id') . ' = ' . (int) $onyx->extension_id)
|
||||
)->execute();
|
||||
|
||||
$this->setDefaultTemplate('mokoonyx', 0);
|
||||
|
||||
// Unlock MokoCassiopeia if present (allow uninstall)
|
||||
$db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->update($db->quoteName('#__extensions'))
|
||||
->set($db->quoteName('locked') . ' = 0')
|
||||
->set($db->quoteName('protected') . ' = 0')
|
||||
->where($db->quoteName('element') . ' = ' . $db->quote('mokocassiopeia'))
|
||||
->where($db->quoteName('type') . ' = ' . $db->quote('template'))
|
||||
)->execute();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback: MokoCassiopeia
|
||||
$query = $db->getQuery(true)
|
||||
->select([$db->quoteName('extension_id'), $db->quoteName('enabled')])
|
||||
->from($db->quoteName('#__extensions'))
|
||||
->where($db->quoteName('element') . ' = ' . $db->quote('mokocassiopeia'))
|
||||
->where($db->quoteName('type') . ' = ' . $db->quote('template'));
|
||||
$template = $db->setQuery($query)->loadObject();
|
||||
|
||||
if ($template)
|
||||
{
|
||||
@@ -247,7 +281,6 @@ class plgSystemMokoWaaSInstallerScript implements InstallerScriptInterface
|
||||
);
|
||||
$db->execute();
|
||||
|
||||
// Set as default site template
|
||||
$this->setDefaultTemplate('mokocassiopeia', 0);
|
||||
|
||||
return;
|
||||
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
<!--
|
||||
Joomla Extension Update Server XML
|
||||
See: https://docs.joomla.org/Deploying_an_Update_Server
|
||||
|
||||
This file is the update server manifest for {{EXTENSION_NAME}}.
|
||||
The Joomla installer polls this URL to check for new versions.
|
||||
|
||||
The manifest.xml in this repository must reference this file:
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
https://git.mokoconsulting.tech/mokoconsulting-tech/MokoWaaS/raw/branch/main/update.xml
|
||||
</server>
|
||||
<server type="extension" priority="2" name="{{EXTENSION_NAME}}">
|
||||
https://raw.githubusercontent.com/mokoconsulting-tech/MokoWaaS/main/update.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
|
||||
When a new release is made, run `make release` or the release workflow to
|
||||
prepend a new <update> entry to this file automatically.
|
||||
-->
|
||||
<updates>
|
||||
<update>
|
||||
<name>{{EXTENSION_NAME}}</name>
|
||||
<description>MokoWaaS — Moko Consulting Joomla extension</description>
|
||||
<element>{{EXTENSION_ELEMENT}}</element>
|
||||
<type>{{EXTENSION_TYPE}}</type>
|
||||
<version>{{VERSION}}</version>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">
|
||||
https://git.mokoconsulting.tech/mokoconsulting-tech/MokoWaaS/releases/download/v{{VERSION}}/{{EXTENSION_ELEMENT}}.zip
|
||||
</downloadurl>
|
||||
<downloadurl type="full" format="zip">
|
||||
https://github.com/mokoconsulting-tech/MokoWaaS/releases/download/v{{VERSION}}/{{EXTENSION_ELEMENT}}.zip
|
||||
</downloadurl>
|
||||
</downloads>
|
||||
<targetplatform name="joomla" version="[56].*"/>
|
||||
<php_minimum>8.1</php_minimum>
|
||||
</update>
|
||||
</updates>
|
||||
+95
-110
@@ -1,113 +1,98 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
SPDX-LICENSE-IDENTIFIER: GPL-3.0-or-later
|
||||
|
||||
# FILE INFORMATION
|
||||
DEFGROUP: Joomla.UpdateServer
|
||||
INGROUP: MokoWaaS
|
||||
REPO: https://github.com/mokoconsulting-tech/mokowaas
|
||||
PATH: /updates.xml
|
||||
BRIEF: Joomla update server XML feed for automatic plugin updates
|
||||
NOTE: This file is automatically updated by GitHub Actions on each release
|
||||
-->
|
||||
<updates>
|
||||
<!-- 1. Development channel (dev) -->
|
||||
<update>
|
||||
<name>MokoWaaS (Dev)</name>
|
||||
<description>MokoWaaS development build — not for production</description>
|
||||
<element>mokowaas</element>
|
||||
<type>plugin</type>
|
||||
<folder>system</folder>
|
||||
<version>02.01.12</version>
|
||||
<stability>dev</stability>
|
||||
<infourl title="MokoWaaS Dev">https://github.com/mokoconsulting-tech/MokoWaaS/releases/tag/development</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://github.com/mokoconsulting-tech/MokoWaaS/releases/download/development/MokoWaaS-02.01.12-dev.zip</downloadurl>
|
||||
</downloads>
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
<targetplatform name="joomla" version="[56]\.[0-9]" />
|
||||
<category>MokoWaaS</category>
|
||||
</update>
|
||||
|
||||
<!-- 2. Alpha channel -->
|
||||
<update>
|
||||
<name>MokoWaaS (Alpha)</name>
|
||||
<description>MokoWaaS alpha — early testing</description>
|
||||
<element>mokowaas</element>
|
||||
<type>plugin</type>
|
||||
<folder>system</folder>
|
||||
<version>02.01.12</version>
|
||||
<stability>alpha</stability>
|
||||
<infourl title="MokoWaaS Alpha">https://github.com/mokoconsulting-tech/MokoWaaS/releases/tag/alpha</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://github.com/mokoconsulting-tech/MokoWaaS/releases/download/alpha/MokoWaaS-02.01.12-alpha.zip</downloadurl>
|
||||
</downloads>
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
<targetplatform name="joomla" version="[56]\.[0-9]" />
|
||||
<category>MokoWaaS</category>
|
||||
</update>
|
||||
|
||||
<!-- 3. Beta channel -->
|
||||
<update>
|
||||
<name>MokoWaaS (Beta)</name>
|
||||
<description>MokoWaaS beta — feature complete, testing in progress</description>
|
||||
<element>mokowaas</element>
|
||||
<type>plugin</type>
|
||||
<folder>system</folder>
|
||||
<version>02.01.12</version>
|
||||
<stability>beta</stability>
|
||||
<infourl title="MokoWaaS Beta">https://github.com/mokoconsulting-tech/MokoWaaS/releases/tag/beta</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://github.com/mokoconsulting-tech/MokoWaaS/releases/download/beta/MokoWaaS-02.01.12-beta.zip</downloadurl>
|
||||
</downloads>
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
<targetplatform name="joomla" version="[56]\.[0-9]" />
|
||||
<category>MokoWaaS</category>
|
||||
</update>
|
||||
|
||||
<!-- 4. Release Candidate channel (rc) -->
|
||||
<update>
|
||||
<name>MokoWaaS (RC)</name>
|
||||
<description>MokoWaaS release candidate — pre-release for testing</description>
|
||||
<element>mokowaas</element>
|
||||
<type>plugin</type>
|
||||
<folder>system</folder>
|
||||
<version>02.01.12</version>
|
||||
<stability>rc</stability>
|
||||
<infourl title="MokoWaaS RC">https://github.com/mokoconsulting-tech/MokoWaaS/releases/tag/release-candidate</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://github.com/mokoconsulting-tech/MokoWaaS/releases/download/release-candidate/MokoWaaS-02.01.12-rc.zip</downloadurl>
|
||||
</downloads>
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
<targetplatform name="joomla" version="[56]\.[0-9]" />
|
||||
<category>MokoWaaS</category>
|
||||
</update>
|
||||
|
||||
<!-- 5. Stable channel (version/XX → main) -->
|
||||
<update>
|
||||
<name>MokoWaaS</name>
|
||||
<description>MokoWaaS system plugin for Joomla</description>
|
||||
<element>mokowaas</element>
|
||||
<type>plugin</type>
|
||||
<folder>system</folder>
|
||||
<version>02.01.12</version>
|
||||
<stability>stable</stability>
|
||||
<infourl title="MokoWaaS">https://github.com/mokoconsulting-tech/mokowaas</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://github.com/mokoconsulting-tech/MokoWaaS/releases/download/v02/MokoWaaS-02.01.11.zip</downloadurl>
|
||||
</downloads>
|
||||
<sha256>c5abccaeecba85ac2f477cddb0212a72d204efaf2065db9d575d535c8cfd1fa9</sha256>
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
<targetplatform name="joomla" version="[56]\.[0-9]" />
|
||||
<category>MokoWaaS</category>
|
||||
</update>
|
||||
<update>
|
||||
<name>System - MokoWaaS</name>
|
||||
<description>System - MokoWaaS update</description>
|
||||
<element>mokowaas</element>
|
||||
<type>plugin</type>
|
||||
<version>02.01.15</version>
|
||||
<client>site</client>
|
||||
<folder>system</folder>
|
||||
<tags><tag>development</tag></tags>
|
||||
<infourl title="System - MokoWaaS">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/v02.01.15</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/mokowaas-02.01.15.zip</downloadurl>
|
||||
<downloadurl type="full" format="tar.gz">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/mokowaas-02.01.15.tar.gz</downloadurl>
|
||||
</downloads>
|
||||
<sha256>81f4741f8cc7063e4287c9e10a9652be105cf092cd91f7188a6cb967c9acb6b9</sha256>
|
||||
<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" />
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
</update>
|
||||
<update>
|
||||
<name>System - MokoWaaS</name>
|
||||
<description>System - MokoWaaS update</description>
|
||||
<element>mokowaas</element>
|
||||
<type>plugin</type>
|
||||
<version>02.01.15</version>
|
||||
<client>site</client>
|
||||
<folder>system</folder>
|
||||
<tags><tag>alpha</tag></tags>
|
||||
<infourl title="System - MokoWaaS">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/v02.01.15</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/mokowaas-02.01.15.zip</downloadurl>
|
||||
<downloadurl type="full" format="tar.gz">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/mokowaas-02.01.15.tar.gz</downloadurl>
|
||||
</downloads>
|
||||
<sha256>81f4741f8cc7063e4287c9e10a9652be105cf092cd91f7188a6cb967c9acb6b9</sha256>
|
||||
<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" />
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
</update>
|
||||
<update>
|
||||
<name>System - MokoWaaS</name>
|
||||
<description>System - MokoWaaS update</description>
|
||||
<element>mokowaas</element>
|
||||
<type>plugin</type>
|
||||
<version>02.01.15</version>
|
||||
<client>site</client>
|
||||
<folder>system</folder>
|
||||
<tags><tag>beta</tag></tags>
|
||||
<infourl title="System - MokoWaaS">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/v02.01.15</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/mokowaas-02.01.15.zip</downloadurl>
|
||||
<downloadurl type="full" format="tar.gz">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/mokowaas-02.01.15.tar.gz</downloadurl>
|
||||
</downloads>
|
||||
<sha256>81f4741f8cc7063e4287c9e10a9652be105cf092cd91f7188a6cb967c9acb6b9</sha256>
|
||||
<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" />
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
</update>
|
||||
<update>
|
||||
<name>System - MokoWaaS</name>
|
||||
<description>System - MokoWaaS update</description>
|
||||
<element>mokowaas</element>
|
||||
<type>plugin</type>
|
||||
<version>02.01.15</version>
|
||||
<client>site</client>
|
||||
<folder>system</folder>
|
||||
<tags><tag>rc</tag></tags>
|
||||
<infourl title="System - MokoWaaS">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/v02.01.15</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/mokowaas-02.01.15.zip</downloadurl>
|
||||
<downloadurl type="full" format="tar.gz">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/mokowaas-02.01.15.tar.gz</downloadurl>
|
||||
</downloads>
|
||||
<sha256>81f4741f8cc7063e4287c9e10a9652be105cf092cd91f7188a6cb967c9acb6b9</sha256>
|
||||
<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" />
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
</update>
|
||||
<update>
|
||||
<name>System - MokoWaaS</name>
|
||||
<description>System - MokoWaaS update</description>
|
||||
<element>mokowaas</element>
|
||||
<type>plugin</type>
|
||||
<version>02.01.15</version>
|
||||
<client>site</client>
|
||||
<folder>system</folder>
|
||||
<tags><tag>stable</tag></tags>
|
||||
<infourl title="System - MokoWaaS">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/v02.01.15</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/mokowaas-02.01.15.zip</downloadurl>
|
||||
<downloadurl type="full" format="tar.gz">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/mokowaas-02.01.15.tar.gz</downloadurl>
|
||||
</downloads>
|
||||
<sha256>81f4741f8cc7063e4287c9e10a9652be105cf092cd91f7188a6cb967c9acb6b9</sha256>
|
||||
<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" />
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
</update>
|
||||
</updates>
|
||||
|
||||
Reference in New Issue
Block a user