Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dc5feaa9aa | |||
| 7281cd1500 | |||
| a1b2bf40ce | |||
| 854dbc6350 | |||
| 1bcbe800e9 | |||
| c8918df03e | |||
| 54236c0d73 | |||
| 33ce9784cc | |||
| 582a16e132 | |||
| e97388c119 | |||
| 954cdaa2ae | |||
| c60be2bf3c |
@@ -5,7 +5,7 @@
|
||||
<display-name>Package - MokoSuiteCross</display-name>
|
||||
<org>MokoConsulting</org>
|
||||
<description>Cross-posting Joomla content to social media, email marketing, and chat platforms</description>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02</version>
|
||||
<license spdx="GPL-3.0-or-later">GNU General Public License v3</license>
|
||||
</identity>
|
||||
<governance>
|
||||
|
||||
@@ -4,15 +4,15 @@
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: mokoplatform.Release
|
||||
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/mokoplatform
|
||||
# INGROUP: mokocli.Release
|
||||
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/mokocli
|
||||
# PATH: /templates/workflows/universal/auto-release.yml.template
|
||||
# VERSION: 05.00.00
|
||||
# BRIEF: Universal build & release � detects platform from manifest.xml
|
||||
#
|
||||
# +========================================================================+
|
||||
# +=======================================================================+
|
||||
# | UNIVERSAL BUILD & RELEASE PIPELINE |
|
||||
# +========================================================================+
|
||||
# +=======================================================================+
|
||||
# | |
|
||||
# | Reads manifest.xml (joomla|dolibarr|generic) to branch logic. |
|
||||
# | |
|
||||
@@ -21,7 +21,7 @@
|
||||
# | dolibarr: mod*.class.php, update.txt, dev version reset |
|
||||
# | generic: README-only, no update stream |
|
||||
# | |
|
||||
# +========================================================================+
|
||||
# +=======================================================================+
|
||||
|
||||
name: "Universal: Build & Release"
|
||||
|
||||
@@ -51,7 +51,7 @@ permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
# ── PR Opened → Rename branch to RC and build RC release ─────────────────────
|
||||
# ── PR Opened → Rename branch to RC and build RC release ─────────────────────────
|
||||
promote-rc:
|
||||
name: Promote to RC
|
||||
runs-on: release
|
||||
@@ -66,25 +66,25 @@ jobs:
|
||||
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Setup mokoplatform tools
|
||||
- name: Setup mokocli tools
|
||||
env:
|
||||
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
||||
run: |
|
||||
if [ -f /opt/mokoplatform/cli/version_bump.php ] && [ -f /opt/mokoplatform/vendor/autoload.php ]; then
|
||||
echo Using pre-installed /opt/mokoplatform
|
||||
echo MOKO_CLI=/opt/mokoplatform/cli >> $GITHUB_ENV
|
||||
if [ -f /opt/mokocli/cli/version_bump.php ] && [ -f /opt/mokocli/vendor/autoload.php ]; then
|
||||
echo Using pre-installed /opt/mokocli
|
||||
echo MOKO_CLI=/opt/mokocli/cli >> $GITHUB_ENV
|
||||
else
|
||||
echo Falling back to fresh clone
|
||||
if ! command -v composer > /dev/null 2>&1; then
|
||||
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1
|
||||
fi
|
||||
rm -rf /tmp/mokoplatform-api
|
||||
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokoplatform.git
|
||||
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokoplatform-api
|
||||
cd /tmp/mokoplatform-api
|
||||
rm -rf /tmp/mokocli
|
||||
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git
|
||||
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
|
||||
cd /tmp/mokocli
|
||||
composer install --no-dev --no-interaction --quiet
|
||||
echo MOKO_CLI=/tmp/mokoplatform-api/cli >> $GITHUB_ENV
|
||||
echo MOKO_CLI=/tmp/mokocli/cli >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Rename branch to rc
|
||||
@@ -109,13 +109,47 @@ jobs:
|
||||
--path . --stability rc --bump minor --branch rc \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
|
||||
- name: Update RC release notes from CHANGELOG.md
|
||||
run: |
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
|
||||
# Extract [Unreleased] section from changelog
|
||||
NOTES=""
|
||||
if [ -f "CHANGELOG.md" ]; then
|
||||
NOTES=$(awk '/^## \[Unreleased\]/{found=1; next} /^## \[/{if(found) exit} found{print}' CHANGELOG.md)
|
||||
fi
|
||||
[ -z "$NOTES" ] && NOTES="Release candidate"
|
||||
|
||||
# Find the RC release and update its body
|
||||
RELEASE_ID=$(curl -sf -H "Authorization: token ${TOKEN}" \
|
||||
"${API_BASE}/releases/tags/release-candidate" \
|
||||
| python3 -c "import json,sys; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
|
||||
|
||||
if [ -n "$RELEASE_ID" ]; then
|
||||
python3 -c "
|
||||
import json, urllib.request
|
||||
body = open('/dev/stdin').read()
|
||||
payload = json.dumps({'body': body}).encode()
|
||||
req = urllib.request.Request(
|
||||
'${API_BASE}/releases/${RELEASE_ID}',
|
||||
data=payload, method='PATCH',
|
||||
headers={
|
||||
'Authorization': 'token ${TOKEN}',
|
||||
'Content-Type': 'application/json'
|
||||
})
|
||||
urllib.request.urlopen(req)
|
||||
" <<< "$NOTES"
|
||||
echo "RC release notes updated from CHANGELOG.md"
|
||||
fi
|
||||
|
||||
- name: Summary
|
||||
if: always()
|
||||
run: |
|
||||
echo "## Promoted to Release Candidate" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Branch renamed to rc, minor bump, RC release built" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# ── Merged PR → Build & Release (or promote RC to stable) ────────────────────
|
||||
# ── Merged PR → Build & Release (or promote RC to stable) ─────────────────────────
|
||||
release:
|
||||
name: Build & Release Pipeline
|
||||
runs-on: release
|
||||
@@ -149,50 +183,131 @@ jobs:
|
||||
fi
|
||||
echo "No conflict markers found"
|
||||
|
||||
- name: Setup mokoplatform tools
|
||||
- name: Setup mokocli tools
|
||||
env:
|
||||
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
||||
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_MIRROR_TOKEN }}"}}'
|
||||
run: |
|
||||
if [ -f /opt/mokoplatform/cli/version_bump.php ] && [ -f /opt/mokoplatform/vendor/autoload.php ]; then
|
||||
echo Using pre-installed /opt/mokoplatform
|
||||
echo MOKO_CLI=/opt/mokoplatform/cli >> $GITHUB_ENV
|
||||
if [ -f /opt/mokocli/cli/version_bump.php ] && [ -f /opt/mokocli/vendor/autoload.php ]; then
|
||||
echo Using pre-installed /opt/mokocli
|
||||
echo MOKO_CLI=/opt/mokocli/cli >> $GITHUB_ENV
|
||||
else
|
||||
echo Falling back to fresh clone
|
||||
if ! command -v composer > /dev/null 2>&1; then
|
||||
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1
|
||||
fi
|
||||
rm -rf /tmp/mokoplatform-api
|
||||
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokoplatform.git
|
||||
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokoplatform-api
|
||||
cd /tmp/mokoplatform-api
|
||||
rm -rf /tmp/mokocli
|
||||
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git
|
||||
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
|
||||
cd /tmp/mokocli
|
||||
composer install --no-dev --no-interaction --quiet
|
||||
echo MOKO_CLI=/tmp/mokoplatform-api/cli >> $GITHUB_ENV
|
||||
echo MOKO_CLI=/tmp/mokocli/cli >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: "Detect platform"
|
||||
id: platform
|
||||
run: |
|
||||
php ${MOKO_CLI}/platform_detect.php --path . --github-output 2>/dev/null || true
|
||||
php ${MOKO_CLI}/manifest_read.php --path . --github-output 2>/dev/null || true
|
||||
|
||||
- name: "Determine version bump level"
|
||||
id: bump
|
||||
run: |
|
||||
# Fix/patch branches: version was already bumped by pre-release, just strip suffix
|
||||
# Feature/dev branches: bump minor for the new stable release
|
||||
HEAD_REF="${{ github.event.pull_request.head.ref || 'dev' }}"
|
||||
case "$HEAD_REF" in
|
||||
fix/*|patch/*|hotfix/*|bugfix/*) BUMP="none" ;;
|
||||
*) BUMP="minor" ;;
|
||||
esac
|
||||
echo "level=${BUMP}" >> "$GITHUB_OUTPUT"
|
||||
echo "Bump level: ${BUMP} (from branch: ${HEAD_REF})"
|
||||
|
||||
- name: "Publish stable release"
|
||||
run: |
|
||||
BUMP_FLAG=""
|
||||
if [ "${{ steps.bump.outputs.level }}" != "none" ]; then
|
||||
BUMP_FLAG="--bump ${{ steps.bump.outputs.level }}"
|
||||
fi
|
||||
php ${MOKO_CLI}/release_publish.php \
|
||||
--path . --stability stable --bump minor --branch main \
|
||||
--path . --stability stable ${BUMP_FLAG} --branch main \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
|
||||
- name: Update release notes from CHANGELOG.md
|
||||
- name: "Read published version"
|
||||
id: version
|
||||
run: |
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
|
||||
# Extract [Unreleased] section from changelog
|
||||
if [ -f "CHANGELOG.md" ]; then
|
||||
NOTES=$(awk '/^## \[Unreleased\]/{found=1; next} /^## \[/{if(found) exit} found{print}' CHANGELOG.md)
|
||||
[ -z "$NOTES" ] && NOTES="Stable release"
|
||||
VERSION=$(php ${MOKO_CLI}/version_read.php --path . 2>/dev/null || echo "")
|
||||
VERSION=$(echo "$VERSION" | sed 's/-\(dev\|alpha\|beta\|rc\)$//')
|
||||
[ -z "$VERSION" ] && VERSION="00.00.00" && echo "skip=true" >> "$GITHUB_OUTPUT"
|
||||
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||
PLATFORM="${{ steps.platform.outputs.platform }}"
|
||||
if [[ "$PLATFORM" == joomla* ]]; then
|
||||
echo "tag=stable" >> "$GITHUB_OUTPUT"
|
||||
echo "release_tag=stable" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
NOTES="Stable release"
|
||||
echo "tag=v${VERSION}" >> "$GITHUB_OUTPUT"
|
||||
echo "release_tag=v${VERSION}" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
echo "branch=main" >> "$GITHUB_OUTPUT"
|
||||
echo "Published version: ${VERSION}"
|
||||
|
||||
- name: "Create semver tag for non-Joomla repos"
|
||||
id: semver
|
||||
if: |
|
||||
steps.version.outputs.skip != 'true' &&
|
||||
!startsWith(steps.platform.outputs.platform, 'joomla')
|
||||
run: |
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
SEMVER_TAG="v${VERSION}"
|
||||
|
||||
echo "Creating semver tag: ${SEMVER_TAG}"
|
||||
|
||||
# Create the git tag via API
|
||||
HTTP_CODE=$(curl -sf -o /dev/null -w "%{http_code}" \
|
||||
-X POST -H "Authorization: token ${TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API_BASE}/tags" \
|
||||
-d "{\"tag_name\":\"${SEMVER_TAG}\",\"target\":\"main\",\"message\":\"Release ${VERSION}\"}" 2>/dev/null || echo "000")
|
||||
|
||||
if [ "$HTTP_CODE" = "201" ] || [ "$HTTP_CODE" = "200" ]; then
|
||||
echo "Created semver tag: ${SEMVER_TAG}"
|
||||
elif [ "$HTTP_CODE" = "409" ]; then
|
||||
echo "Semver tag ${SEMVER_TAG} already exists (skipped)"
|
||||
else
|
||||
echo "::warning::Failed to create semver tag ${SEMVER_TAG} (HTTP ${HTTP_CODE})"
|
||||
fi
|
||||
|
||||
# Update release body via API
|
||||
RELEASE_ID=$(curl -sf -H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \
|
||||
"${API_BASE}/releases/tags/stable" | python3 -c "import json,sys; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
|
||||
echo "semver_tag=${SEMVER_TAG}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Update release notes and promote changelog
|
||||
run: |
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
|
||||
# Get the stable release info (version and ID)
|
||||
RELEASE_JSON=$(curl -sf -H "Authorization: token ${TOKEN}" \
|
||||
"${API_BASE}/releases/tags/stable" 2>/dev/null || echo '{}')
|
||||
RELEASE_ID=$(python3 -c "import json,sys; print(json.load(sys.stdin).get('id',''))" <<< "$RELEASE_JSON" 2>/dev/null || true)
|
||||
# Extract version from release name (e.g. "06.17.00" or "v06.17.00")
|
||||
VERSION=$(python3 -c "
|
||||
import json, sys, re
|
||||
r = json.load(sys.stdin)
|
||||
name = r.get('name', '')
|
||||
m = re.search(r'(\d+\.\d+\.\d+)', name)
|
||||
print(m.group(1) if m else '')
|
||||
" <<< "$RELEASE_JSON" 2>/dev/null || true)
|
||||
|
||||
# Extract [Unreleased] section from changelog
|
||||
NOTES=""
|
||||
if [ -f "CHANGELOG.md" ]; then
|
||||
NOTES=$(awk '/^## \[Unreleased\]/{found=1; next} /^## \[/{if(found) exit} found{print}' CHANGELOG.md)
|
||||
fi
|
||||
[ -z "$NOTES" ] && NOTES="Stable release"
|
||||
|
||||
# Update release body via API
|
||||
if [ -n "$RELEASE_ID" ]; then
|
||||
python3 -c "
|
||||
import json, urllib.request
|
||||
@@ -202,7 +317,7 @@ jobs:
|
||||
'${API_BASE}/releases/${RELEASE_ID}',
|
||||
data=payload, method='PATCH',
|
||||
headers={
|
||||
'Authorization': 'token ${{ secrets.MOKOGITEA_TOKEN }}',
|
||||
'Authorization': 'token ${TOKEN}',
|
||||
'Content-Type': 'application/json'
|
||||
})
|
||||
urllib.request.urlopen(req)
|
||||
@@ -210,6 +325,24 @@ jobs:
|
||||
echo "Release notes updated from CHANGELOG.md"
|
||||
fi
|
||||
|
||||
# Promote [Unreleased] → [version] in CHANGELOG.md and reset
|
||||
if [ -n "$VERSION" ] && [ -f "CHANGELOG.md" ]; then
|
||||
DATE=$(date +%Y-%m-%d)
|
||||
python3 -c "
|
||||
import sys
|
||||
version, date = sys.argv[1], sys.argv[2]
|
||||
content = open('CHANGELOG.md').read()
|
||||
old = '## [Unreleased]'
|
||||
new = f'## [Unreleased]\n\n## [{version}] --- {date}'
|
||||
content = content.replace(old, new, 1)
|
||||
open('CHANGELOG.md', 'w').write(content)
|
||||
" "$VERSION" "$DATE"
|
||||
git add CHANGELOG.md
|
||||
git commit -m "chore: promote changelog [Unreleased] → [${VERSION}]" || true
|
||||
git push origin main || true
|
||||
echo "Changelog promoted: [Unreleased] → [${VERSION}]"
|
||||
fi
|
||||
|
||||
# -- STEP 9: Mirror to GitHub (stable only) --------------------------------
|
||||
- name: "Step 9: Mirror release to GitHub"
|
||||
if: >-
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: mokoplatform.Automation
|
||||
# VERSION: 01.04.00
|
||||
# INGROUP: mokocli.Automation
|
||||
# VERSION: 01.04.02
|
||||
# BRIEF: Auto-create feature branch when an issue is opened
|
||||
|
||||
name: "Universal: Issue Branch"
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
steps:
|
||||
- name: Create branch and comment
|
||||
run: |
|
||||
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
TOKEN="${{ secrets.GA_TOKEN }}"
|
||||
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
|
||||
ISSUE_NUM="${{ github.event.issue.number }}"
|
||||
ISSUE_TITLE="${{ github.event.issue.title }}"
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: mokoplatform.CI
|
||||
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/mokoplatform
|
||||
# INGROUP: moko-platform.CI
|
||||
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/moko-platform
|
||||
# PATH: /templates/workflows/universal/pr-check.yml.template
|
||||
# VERSION: 09.23.00
|
||||
# BRIEF: PR gate — branch policy + code validation before merge
|
||||
@@ -185,11 +185,11 @@ jobs:
|
||||
echo "::error file=${file}::Missing JEXEC guard: ${file}"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
done < <(find . -name "*.php" \( -path "*/source/*" -o -path "*/src/*" \) -not -path "./.git/*" -not -path "./vendor/*" -print0)
|
||||
done < <(find . -name "*.php" -path "*/src/*" -not -path "./.git/*" -not -path "./vendor/*" -print0)
|
||||
if [ "$ERRORS" -gt 0 ]; then
|
||||
echo "::error::${ERRORS} PHP file(s) missing defined('_JEXEC') or die guard"
|
||||
echo "## JEXEC Guard Check: Failed" >> $GITHUB_STEP_SUMMARY
|
||||
echo "${ERRORS} file(s) are missing the Joomla execution guard." >> $GITHUB_STEP_SUMMARY
|
||||
echo "${ERRORS} file(s) in src/ are missing the Joomla execution guard." >> $GITHUB_STEP_SUMMARY
|
||||
exit 1
|
||||
fi
|
||||
echo "JEXEC guard: OK"
|
||||
@@ -198,8 +198,7 @@ jobs:
|
||||
if: steps.platform.outputs.platform == 'joomla'
|
||||
run: |
|
||||
MISSING=0
|
||||
SOURCE_DIR="source"
|
||||
[ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="src"
|
||||
SOURCE_DIR="src"
|
||||
[ ! -d "$SOURCE_DIR" ] && exit 0
|
||||
while IFS= read -r dir; do
|
||||
if [ ! -f "${dir}/index.html" ]; then
|
||||
@@ -247,7 +246,7 @@ jobs:
|
||||
echo "joomla.asset.json: valid"
|
||||
fi
|
||||
|
||||
# Validate all XML files in source/src are well-formed
|
||||
# Validate all XML files in src/ are well-formed
|
||||
XML_ERRORS=0
|
||||
if command -v php &> /dev/null; then
|
||||
while IFS= read -r -d '' xmlfile; do
|
||||
@@ -478,11 +477,10 @@ jobs:
|
||||
|
||||
- name: Verify package source
|
||||
run: |
|
||||
SOURCE_DIR="source"
|
||||
[ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="src"
|
||||
SOURCE_DIR="src"
|
||||
[ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs"
|
||||
if [ ! -d "$SOURCE_DIR" ]; then
|
||||
echo "::warning::No source/, src/, or htdocs/ directory"
|
||||
echo "::warning::No src/ or htdocs/ directory"
|
||||
exit 0
|
||||
fi
|
||||
FILE_COUNT=$(find "$SOURCE_DIR" -type f | wc -l)
|
||||
|
||||
@@ -4,23 +4,26 @@
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: mokoplatform.Release
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform
|
||||
# INGROUP: mokocli.Release
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
# PATH: /templates/workflows/universal/pre-release.yml.template
|
||||
# VERSION: 05.01.00
|
||||
# BRIEF: Manual pre-release -- builds dev/alpha/beta/rc packages from any branch
|
||||
# BRIEF: Auto pre-release on push to dev/alpha/beta/rc branches
|
||||
|
||||
name: "Universal: Pre-Release"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
pull_request_target:
|
||||
types: [synchronize, opened, reopened]
|
||||
branches:
|
||||
- main
|
||||
- 'fix/**'
|
||||
- 'patch/**'
|
||||
- 'hotfix/**'
|
||||
- 'bugfix/**'
|
||||
- 'chore/**'
|
||||
- alpha
|
||||
- beta
|
||||
- rc
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
stability:
|
||||
@@ -43,12 +46,11 @@ env:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: "Build Pre-Release (${{ inputs.stability || 'development' }})"
|
||||
name: "Build Pre-Release (${{ inputs.stability || github.ref_name }})"
|
||||
runs-on: release
|
||||
if: >-
|
||||
github.event_name == 'workflow_dispatch' ||
|
||||
(github.event_name == 'pull_request' && github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'dev') ||
|
||||
(github.event_name == 'pull_request_target' && github.event.pull_request.base.ref == 'main')
|
||||
github.event_name == 'push'
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -56,40 +58,47 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || '' }}
|
||||
ref: ${{ github.ref_name }}
|
||||
|
||||
- name: Setup mokoplatform tools
|
||||
- name: Setup mokocli tools
|
||||
env:
|
||||
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
||||
run: |
|
||||
# Use pre-installed /opt/mokoplatform if available (updated by cron every 6h)
|
||||
if [ -f /opt/mokoplatform/cli/version_bump.php ] && [ -f /opt/mokoplatform/cli/manifest_element.php ] && [ -f /opt/mokoplatform/vendor/autoload.php ]; then
|
||||
echo Using pre-installed /opt/mokoplatform
|
||||
echo MOKO_CLI=/opt/mokoplatform/cli >> $GITHUB_ENV
|
||||
# Use pre-installed /opt/mokocli if available (updated by cron every 6h)
|
||||
if [ -f /opt/mokocli/cli/version_bump.php ] && [ -f /opt/mokocli/cli/manifest_element.php ] && [ -f /opt/mokocli/vendor/autoload.php ]; then
|
||||
echo Using pre-installed /opt/mokocli
|
||||
echo MOKO_CLI=/opt/mokocli/cli >> $GITHUB_ENV
|
||||
else
|
||||
echo Falling back to fresh clone
|
||||
if ! command -v composer > /dev/null 2>&1; then
|
||||
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1
|
||||
fi
|
||||
rm -rf /tmp/mokoplatform-api
|
||||
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokoplatform.git
|
||||
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokoplatform-api
|
||||
cd /tmp/mokoplatform-api && composer install --no-dev --no-interaction --quiet
|
||||
echo MOKO_CLI=/tmp/mokoplatform-api/cli >> $GITHUB_ENV
|
||||
rm -rf /tmp/mokocli
|
||||
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git
|
||||
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
|
||||
cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet
|
||||
echo MOKO_CLI=/tmp/mokocli/cli >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Detect platform
|
||||
id: platform
|
||||
run: |
|
||||
# Auto-detect and update platform if not set in manifest
|
||||
php ${MOKO_CLI}/platform_detect.php --path . --github-output 2>/dev/null || true
|
||||
php ${MOKO_CLI}/manifest_read.php --path . --github-output
|
||||
|
||||
- name: Resolve metadata and bump version
|
||||
id: meta
|
||||
run: |
|
||||
# Auto-detect stability: RC for PRs targeting main, else use input or default to development
|
||||
if [ "${{ github.event_name }}" = "pull_request_target" ] && [ "${{ github.event.pull_request.base.ref }}" = "main" ]; then
|
||||
STABILITY="release-candidate"
|
||||
# Auto-detect stability from branch name on push, or use input on dispatch
|
||||
if [ "${{ github.event_name }}" = "push" ]; then
|
||||
case "${{ github.ref_name }}" in
|
||||
rc) STABILITY="release-candidate" ;;
|
||||
alpha) STABILITY="alpha" ;;
|
||||
beta) STABILITY="beta" ;;
|
||||
*) STABILITY="development" ;;
|
||||
esac
|
||||
else
|
||||
STABILITY="${{ inputs.stability || 'development' }}"
|
||||
fi
|
||||
@@ -164,7 +173,7 @@ jobs:
|
||||
php ${MOKO_CLI}/release_create.php \
|
||||
--path . --version "$VERSION" --tag "$TAG" \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
|
||||
--repo "${GITEA_REPO}" --branch dev --prerelease
|
||||
--repo "${GITEA_REPO}" --branch "${{ github.ref_name }}" --prerelease
|
||||
|
||||
- name: Update release notes from CHANGELOG.md
|
||||
run: |
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: mokoplatform.Validation
|
||||
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/mokoplatform
|
||||
# INGROUP: mokocli.Validation
|
||||
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/mokocli
|
||||
# PATH: /templates/workflows/joomla/repo_health.yml.template
|
||||
# VERSION: 09.23.00
|
||||
# BRIEF: Enforces repository guardrails by validating scripts governance, tooling availability, and core repository health artifacts.
|
||||
@@ -33,7 +33,8 @@ on:
|
||||
- scripts
|
||||
- repo
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -296,19 +297,17 @@ jobs:
|
||||
missing_required=()
|
||||
missing_optional=()
|
||||
|
||||
# Source directory: source/, src/, or htdocs/ (any is valid for extension repos)
|
||||
# Source directory: src/ or htdocs/ (either is valid for extension repos)
|
||||
SOURCE_DIR=""
|
||||
if [ -d "source" ]; then
|
||||
SOURCE_DIR="source"
|
||||
elif [ -d "src" ]; then
|
||||
if [ -d "src" ]; then
|
||||
SOURCE_DIR="src"
|
||||
elif [ -d "htdocs" ]; then
|
||||
SOURCE_DIR="htdocs"
|
||||
elif [ -d "deploy" ] || [ -d "cli" ] || [ -d "monitoring" ]; then
|
||||
# Platform/tooling repos don't need source/
|
||||
# Platform/tooling repos don't need src/
|
||||
SOURCE_DIR=""
|
||||
else
|
||||
missing_required+=("source/ or src/ or htdocs/ (source directory required)")
|
||||
missing_required+=("src/ or htdocs/ (source directory required)")
|
||||
fi
|
||||
|
||||
for item in "${required_artifacts[@]}"; do
|
||||
|
||||
+6
-7
@@ -1,7 +1,11 @@
|
||||
# Changelog
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [01.04.01] --- 2026-06-21
|
||||
|
||||
|
||||
## [01.04.01] --- 2026-06-21
|
||||
|
||||
|
||||
## [01.04.00] --- 2026-06-21
|
||||
|
||||
@@ -12,7 +16,7 @@
|
||||
## [01.03.00] --- 2026-06-21
|
||||
|
||||
|
||||
<!-- VERSION: 01.04.00 -->
|
||||
<!-- VERSION: 01.04.02 -->
|
||||
|
||||
All notable changes to MokoSuiteCross will be documented in this file.
|
||||
|
||||
@@ -238,8 +242,3 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
||||
- Perfect Publisher Pro migration tool in installer script
|
||||
- Message template system with per-platform placeholders
|
||||
- Post queue with scheduled posting, retry logic, and delivery tracking
|
||||
|
||||
## [01.00] - 2026-05-28
|
||||
|
||||
### Added
|
||||
- Initial release
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# MokoSuiteCross
|
||||
|
||||
<!-- VERSION: 01.04.00 -->
|
||||
<!-- VERSION: 01.04.02 -->
|
||||
|
||||
Cross-posting Joomla content to social media, email marketing, and chat platforms for Joomla 5/6.
|
||||
|
||||
|
||||
@@ -1,237 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# ============================================================================
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Automation.CI
|
||||
# INGROUP: moko-platform.Automation
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
|
||||
# PATH: /automation/ci-issue-reporter.sh
|
||||
# VERSION: 09.23.00
|
||||
# BRIEF: Creates or updates a Gitea issue when a CI gate fails.
|
||||
# Deduplicates by searching open issues with the "ci-auto" label
|
||||
# whose title matches the gate. If a matching issue exists, a comment
|
||||
# is appended instead of opening a duplicate.
|
||||
# ============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ── Defaults ────────────────────────────────────────────────────────────────
|
||||
GITEA_URL="${GITEA_URL:-https://git.mokoconsulting.tech}"
|
||||
GITEA_TOKEN="${GITEA_TOKEN:-}"
|
||||
REPO="${GITHUB_REPOSITORY:-}"
|
||||
RUN_URL="${GITHUB_SERVER_URL:-${GITEA_URL}}/${REPO}/actions/runs/${GITHUB_RUN_ID:-0}"
|
||||
LABEL_NAME="ci-auto"
|
||||
LABEL_COLOR="#e11d48"
|
||||
|
||||
GATE=""
|
||||
DETAILS=""
|
||||
SEVERITY="error"
|
||||
WORKFLOW=""
|
||||
|
||||
# ── Parse arguments ─────────────────────────────────────────────────────────
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: ci-issue-reporter.sh --gate NAME --details TEXT [OPTIONS]
|
||||
|
||||
Required:
|
||||
--gate CI gate name (e.g. "Code Quality", "Self-Health")
|
||||
--details Human-readable failure description
|
||||
|
||||
Optional:
|
||||
--severity "error" (default) or "warning"
|
||||
--workflow Workflow name for the issue title
|
||||
--repo owner/repo (default: \$GITHUB_REPOSITORY)
|
||||
--run-url URL to the CI run (auto-detected from env)
|
||||
--token Gitea API token (default: \$GITEA_TOKEN)
|
||||
--url Gitea base URL (default: \$GITEA_URL)
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--gate) GATE="$2"; shift 2 ;;
|
||||
--details) DETAILS="$2"; shift 2 ;;
|
||||
--severity) SEVERITY="$2"; shift 2 ;;
|
||||
--workflow) WORKFLOW="$2"; shift 2 ;;
|
||||
--repo) REPO="$2"; shift 2 ;;
|
||||
--run-url) RUN_URL="$2"; shift 2 ;;
|
||||
--token) GITEA_TOKEN="$2"; shift 2 ;;
|
||||
--url) GITEA_URL="$2"; shift 2 ;;
|
||||
-h|--help) usage ;;
|
||||
*) echo "Unknown option: $1"; usage ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -z "$GATE" ]] && { echo "ERROR: --gate is required"; usage; }
|
||||
[[ -z "$DETAILS" ]] && { echo "ERROR: --details is required"; usage; }
|
||||
[[ -z "$GITEA_TOKEN" ]] && { echo "ERROR: GITEA_TOKEN not set"; exit 1; }
|
||||
[[ -z "$REPO" ]] && { echo "ERROR: GITHUB_REPOSITORY not set"; exit 1; }
|
||||
|
||||
API="${GITEA_URL}/api/v1/repos/${REPO}"
|
||||
|
||||
# ── Build title ─────────────────────────────────────────────────────────────
|
||||
if [[ -n "$WORKFLOW" ]]; then
|
||||
TITLE="[CI] ${WORKFLOW}: ${GATE} failed"
|
||||
else
|
||||
TITLE="[CI] ${GATE} failed"
|
||||
fi
|
||||
|
||||
# ── Ensure label exists ─────────────────────────────────────────────────────
|
||||
ensure_label() {
|
||||
local exists
|
||||
exists=$(curl -sf -o /dev/null -w '%{http_code}' \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
"${API}/labels" 2>/dev/null || echo "000")
|
||||
|
||||
if [[ "$exists" == "200" ]]; then
|
||||
# Check if label already exists
|
||||
local found
|
||||
found=$(curl -sf \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
"${API}/labels" 2>/dev/null \
|
||||
| grep -o "\"name\":\"${LABEL_NAME}\"" || true)
|
||||
|
||||
if [[ -z "$found" ]]; then
|
||||
curl -sf -X POST \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API}/labels" \
|
||||
-d "{\"name\":\"${LABEL_NAME}\",\"color\":\"${LABEL_COLOR}\",\"description\":\"Auto-created by CI issue reporter\"}" \
|
||||
> /dev/null 2>&1 || true
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# ── Search for existing open issue ──────────────────────────────────────────
|
||||
find_existing_issue() {
|
||||
# URL-encode the gate name for the query
|
||||
local query
|
||||
query=$(printf '%s' "[CI] ${GATE}" | sed 's/ /%20/g; s/\[/%5B/g; s/\]/%5D/g')
|
||||
|
||||
local response
|
||||
response=$(curl -sf \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
"${API}/issues?type=issues&state=open&labels=${LABEL_NAME}&q=${query}&limit=5" \
|
||||
2>/dev/null || echo "[]")
|
||||
|
||||
# Extract the first matching issue number
|
||||
echo "$response" \
|
||||
| grep -oP '"number":\s*\K[0-9]+' \
|
||||
| head -1
|
||||
}
|
||||
|
||||
# ── Build issue body ────────────────────────────────────────────────────────
|
||||
build_body() {
|
||||
local severity_badge
|
||||
if [[ "$SEVERITY" == "error" ]]; then
|
||||
severity_badge="**Severity:** Error"
|
||||
else
|
||||
severity_badge="**Severity:** Warning"
|
||||
fi
|
||||
|
||||
cat <<BODY
|
||||
## CI Gate Failure: ${GATE}
|
||||
|
||||
${severity_badge}
|
||||
**Workflow:** ${WORKFLOW:-unknown}
|
||||
**Branch:** ${GITHUB_REF_NAME:-unknown}
|
||||
**Commit:** \`${GITHUB_SHA:0:8}\`
|
||||
**Run:** [View CI run](${RUN_URL})
|
||||
|
||||
### Details
|
||||
|
||||
${DETAILS}
|
||||
|
||||
### Resolution
|
||||
|
||||
Fix the issue described above and push a new commit. This issue will be closed automatically when the gate passes, or can be closed manually.
|
||||
|
||||
---
|
||||
*Auto-created by [ci-issue-reporter](${GITEA_URL}/${REPO}/src/branch/main/automation/ci-issue-reporter.sh)*
|
||||
BODY
|
||||
}
|
||||
|
||||
# ── Build comment body (for existing issues) ────────────────────────────────
|
||||
build_comment() {
|
||||
cat <<COMMENT
|
||||
### CI failure recurrence
|
||||
|
||||
**Branch:** ${GITHUB_REF_NAME:-unknown}
|
||||
**Commit:** \`${GITHUB_SHA:0:8}\`
|
||||
**Run:** [View CI run](${RUN_URL})
|
||||
|
||||
${DETAILS}
|
||||
COMMENT
|
||||
}
|
||||
|
||||
# ── Main ────────────────────────────────────────────────────────────────────
|
||||
ensure_label
|
||||
|
||||
EXISTING=$(find_existing_issue)
|
||||
|
||||
if [[ -n "$EXISTING" ]]; then
|
||||
# Append comment to existing issue
|
||||
COMMENT_BODY=$(build_comment)
|
||||
COMMENT_JSON=$(printf '%s' "$COMMENT_BODY" | python3 -c "
|
||||
import sys, json
|
||||
print(json.dumps({'body': sys.stdin.read()}))" 2>/dev/null)
|
||||
|
||||
HTTP=$(curl -sf -o /dev/null -w '%{http_code}' -X POST \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API}/issues/${EXISTING}/comments" \
|
||||
-d "${COMMENT_JSON}" 2>/dev/null || echo "000")
|
||||
|
||||
if [[ "$HTTP" == "201" ]]; then
|
||||
echo "Commented on existing issue #${EXISTING}"
|
||||
else
|
||||
echo "WARNING: Failed to comment on issue #${EXISTING} (HTTP ${HTTP})"
|
||||
fi
|
||||
else
|
||||
# Create new issue
|
||||
ISSUE_BODY=$(build_body)
|
||||
ISSUE_JSON=$(python3 -c "
|
||||
import sys, json
|
||||
body = sys.stdin.read()
|
||||
print(json.dumps({
|
||||
'title': sys.argv[1],
|
||||
'body': body,
|
||||
'labels': []
|
||||
}))" "$TITLE" <<< "$ISSUE_BODY" 2>/dev/null)
|
||||
|
||||
# Create the issue
|
||||
RESPONSE=$(curl -sf -X POST \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API}/issues" \
|
||||
-d "${ISSUE_JSON}" 2>/dev/null || echo "{}")
|
||||
|
||||
ISSUE_NUM=$(echo "$RESPONSE" | grep -oP '"number":\s*\K[0-9]+' | head -1)
|
||||
|
||||
if [[ -n "$ISSUE_NUM" ]]; then
|
||||
# Apply label (separate call — more reliable across Gitea versions)
|
||||
LABEL_ID=$(curl -sf \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
"${API}/labels" 2>/dev/null \
|
||||
| grep -oP "\"id\":\s*\K[0-9]+(?=[^}]*\"name\":\s*\"${LABEL_NAME}\")" \
|
||||
| head -1 || true)
|
||||
|
||||
if [[ -n "$LABEL_ID" ]]; then
|
||||
curl -sf -X POST \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API}/issues/${ISSUE_NUM}/labels" \
|
||||
-d "{\"labels\":[${LABEL_ID}]}" \
|
||||
> /dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
echo "Created issue #${ISSUE_NUM}: ${TITLE}"
|
||||
else
|
||||
echo "WARNING: Failed to create issue"
|
||||
echo "Response: ${RESPONSE}"
|
||||
fi
|
||||
fi
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="component" method="upgrade">
|
||||
<name>com_mokosuitecross</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="content" method="upgrade">
|
||||
<name>Content - MokoSuiteCross</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - ActivityPub (Fediverse)</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Google Blogger</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Bluesky</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Brevo (Sendinblue)</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Constant Contact</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - ConvertKit</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Dev.to</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Discord</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Facebook / Meta</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Ghost</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Google Business Profile</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Google Chat</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Hashnode</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - LinkedIn</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Mailchimp</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Mastodon</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Matrix / Element</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Medium</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - MokoSuiteCalendar Events</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - MokoSuiteGallery</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Nostr</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Ntfy Push Notifications</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Pinterest</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Reddit</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - RSS Feed</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - SendGrid</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Slack</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Microsoft Teams</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Telegram</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Threads (Meta)</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - TikTok</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Tumblr</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - X / Twitter</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - Generic Webhook</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - WhatsApp Business</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="mokosuitecross" method="upgrade">
|
||||
<name>MokoSuiteCross - WordPress</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="system" method="upgrade">
|
||||
<name>System - MokoSuiteCross</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="system" method="upgrade">
|
||||
<name>System - MokoSuiteCross Events</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="system" method="upgrade">
|
||||
<name>System - MokoSuiteCross Gallery</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="task" method="upgrade">
|
||||
<name>Task - MokoSuiteCross Queue Processor</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="webservices" method="upgrade">
|
||||
<name>Web Services - MokoSuiteCross</name>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<extension type="package" method="upgrade">
|
||||
<name>MokoSuiteCross</name>
|
||||
<packagename>mokosuitecross</packagename>
|
||||
<version>01.04.00</version>
|
||||
<version>01.04.02-dev</version>
|
||||
<creationDate>2026-05-28</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
|
||||
Reference in New Issue
Block a user