Merge pull request 'Release 02.09.00: CI fixes, update server standard, Joomla skill' (#44) from dev into main
Universal: Cascade Main → Dev / Cascade main → branches (push) Has been cancelled
Joomla: Repo Health / Access control (push) Has been cancelled
Joomla: Repo Health / Release configuration (push) Has been cancelled
Joomla: Repo Health / Scripts governance (push) Has been cancelled
Joomla: Repo Health / Repository health (push) Has been cancelled
Universal: Cascade Main → Dev / Cascade main → branches (push) Has been cancelled
Joomla: Repo Health / Access control (push) Has been cancelled
Joomla: Repo Health / Release configuration (push) Has been cancelled
Joomla: Repo Health / Scripts governance (push) Has been cancelled
Joomla: Repo Health / Repository health (push) Has been cancelled
This commit was merged in pull request #44.
This commit is contained in:
@@ -26,7 +26,8 @@
|
|||||||
name: "Universal: Build & Release"
|
name: "Universal: Build & Release"
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
pull_request:
|
||||||
|
types: [closed]
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
paths:
|
paths:
|
||||||
@@ -47,7 +48,8 @@ jobs:
|
|||||||
release:
|
release:
|
||||||
name: Build & Release Pipeline
|
name: Build & Release Pipeline
|
||||||
runs-on: release
|
runs-on: release
|
||||||
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
|
if: >-
|
||||||
|
github.event.pull_request.merged == true || github.event_name == 'workflow_dispatch'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
@@ -94,9 +96,9 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
MAJOR=$(echo "$VERSION" | cut -d. -f1)
|
MAJOR=$(echo "$VERSION" | cut -d. -f1)
|
||||||
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||||
echo "release_tag=v${MAJOR}" >> "$GITHUB_OUTPUT"
|
echo "release_tag=stable" >> "$GITHUB_OUTPUT"
|
||||||
echo "skip=false" >> "$GITHUB_OUTPUT"
|
echo "skip=false" >> "$GITHUB_OUTPUT"
|
||||||
echo "branch=version/${MAJOR}" >> "$GITHUB_OUTPUT"
|
echo "branch=main" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: "Step 1b: Bump version"
|
- name: "Step 1b: Bump version"
|
||||||
id: bump
|
id: bump
|
||||||
@@ -261,6 +263,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||||
php /tmp/moko-platform-api/cli/badge_update.php --path . --version "${VERSION}" 2>/dev/null || true
|
php /tmp/moko-platform-api/cli/badge_update.php --path . --version "${VERSION}" 2>/dev/null || true
|
||||||
|
php /tmp/moko-platform-api/cli/version_check.php --path . --fix 2>/dev/null || true
|
||||||
|
|
||||||
- name: "Step 5: Write update stream"
|
- name: "Step 5: Write update stream"
|
||||||
if: >-
|
if: >-
|
||||||
@@ -268,6 +271,15 @@ jobs:
|
|||||||
steps.platform.outputs.platform == 'joomla'
|
steps.platform.outputs.platform == 'joomla'
|
||||||
run: |
|
run: |
|
||||||
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||||
|
|
||||||
|
# Fetch latest updates.xml from main so preserve logic has all channels
|
||||||
|
GA_TOKEN="${{ secrets.GA_TOKEN }}"
|
||||||
|
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
|
||||||
|
curl -sf -H "Authorization: token ${GA_TOKEN}" \
|
||||||
|
"${API}/contents/updates.xml?ref=main" 2>/dev/null | \
|
||||||
|
python3 -c "import sys,json,base64; print(base64.b64decode(json.load(sys.stdin)['content']).decode())" \
|
||||||
|
> updates.xml 2>/dev/null || true
|
||||||
|
|
||||||
php /tmp/moko-platform-api/cli/updates_xml_build.php \
|
php /tmp/moko-platform-api/cli/updates_xml_build.php \
|
||||||
--path . --version "${VERSION}" --stability stable \
|
--path . --version "${VERSION}" --stability stable \
|
||||||
--gitea-url "${GITEA_URL}" --org "${GITEA_ORG}" --repo "${GITEA_REPO}" \
|
--gitea-url "${GITEA_URL}" --org "${GITEA_ORG}" --repo "${GITEA_REPO}" \
|
||||||
@@ -295,9 +307,7 @@ jobs:
|
|||||||
# -- STEP 6: Create tag ---------------------------------------------------
|
# -- STEP 6: Create tag ---------------------------------------------------
|
||||||
- name: "Step 6: Create git tag"
|
- name: "Step 6: Create git tag"
|
||||||
if: >-
|
if: >-
|
||||||
steps.version.outputs.skip != 'true' &&
|
steps.version.outputs.skip != 'true'
|
||||||
steps.check.outputs.tag_exists != 'true' &&
|
|
||||||
steps.version.outputs.is_minor == 'true'
|
|
||||||
run: |
|
run: |
|
||||||
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
|
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
|
||||||
# Only create the major release tag if it doesn't exist yet
|
# Only create the major release tag if it doesn't exist yet
|
||||||
@@ -337,6 +347,8 @@ jobs:
|
|||||||
[ -z "$NOTES" ] && NOTES="Release ${VERSION}"
|
[ -z "$NOTES" ] && NOTES="Release ${VERSION}"
|
||||||
|
|
||||||
# Build release name: "Pretty Name VERSION (type_element-VERSION)"
|
# Build release name: "Pretty Name VERSION (type_element-VERSION)"
|
||||||
|
# Strip existing type prefix to prevent duplication
|
||||||
|
EXT_ELEMENT=$(echo "$EXT_ELEMENT" | sed -E 's/^(pkg_|com_|mod_|plg_[a-z]+_|tpl_|lib_)//')
|
||||||
TYPE_PREFIX=""
|
TYPE_PREFIX=""
|
||||||
case "${EXT_TYPE}" in
|
case "${EXT_TYPE}" in
|
||||||
plugin) TYPE_PREFIX="plg_${EXT_FOLDER}_" ;;
|
plugin) TYPE_PREFIX="plg_${EXT_FOLDER}_" ;;
|
||||||
@@ -407,6 +419,13 @@ jobs:
|
|||||||
# ZIP name: type_folder_element-VERSION (e.g. plg_system_mokojgdpc-01.01.00.zip)
|
# ZIP name: type_folder_element-VERSION (e.g. plg_system_mokojgdpc-01.01.00.zip)
|
||||||
EXT_TYPE=$(sed -n 's/.*<extension[^>]*type="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
|
EXT_TYPE=$(sed -n 's/.*<extension[^>]*type="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
|
||||||
EXT_FOLDER=$(sed -n 's/.*<extension[^>]*group="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
|
EXT_FOLDER=$(sed -n 's/.*<extension[^>]*group="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
|
||||||
|
# For packages, prefer <packagename> over filename-derived element
|
||||||
|
if [ "$EXT_TYPE" = "package" ]; then
|
||||||
|
PKG_NAME=$(sed -n 's/.*<packagename>\([^<]*\)<\/packagename>.*/\1/p' "$MANIFEST" 2>/dev/null | head -1)
|
||||||
|
[ -n "$PKG_NAME" ] && EXT_ELEMENT="$PKG_NAME"
|
||||||
|
fi
|
||||||
|
# Strip existing type prefix to prevent duplication (e.g. pkg_mokowaas → mokowaas)
|
||||||
|
EXT_ELEMENT=$(echo "$EXT_ELEMENT" | sed -E 's/^(pkg_|com_|mod_|plg_[a-z]+_|tpl_|lib_)//')
|
||||||
TYPE_PREFIX=""
|
TYPE_PREFIX=""
|
||||||
case "${EXT_TYPE}" in
|
case "${EXT_TYPE}" in
|
||||||
plugin) TYPE_PREFIX="plg_${EXT_FOLDER}_" ;;
|
plugin) TYPE_PREFIX="plg_${EXT_FOLDER}_" ;;
|
||||||
@@ -442,110 +461,35 @@ jobs:
|
|||||||
SHA256_ZIP=$(sha256sum "/tmp/${ZIP_NAME}" | cut -d' ' -f1)
|
SHA256_ZIP=$(sha256sum "/tmp/${ZIP_NAME}" | cut -d' ' -f1)
|
||||||
SHA256_TAR=$(sha256sum "/tmp/${TAR_NAME}" | cut -d' ' -f1)
|
SHA256_TAR=$(sha256sum "/tmp/${TAR_NAME}" | cut -d' ' -f1)
|
||||||
|
|
||||||
# -- Delete existing assets with same name before uploading ------
|
# -- Get existing assets for cleanup --------------------------------
|
||||||
ASSETS=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
ASSETS=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
||||||
"${API_BASE}/releases/${RELEASE_ID}/assets" 2>/dev/null || echo "[]")
|
"${API_BASE}/releases/${RELEASE_ID}/assets" 2>/dev/null || echo "[]")
|
||||||
for ASSET_NAME in "$ZIP_NAME" "$TAR_NAME"; do
|
|
||||||
|
# -- Create per-file .sha256 checksum files -------------------------
|
||||||
|
echo "${SHA256_ZIP} ${ZIP_NAME}" > "/tmp/${ZIP_NAME}.sha256"
|
||||||
|
echo "${SHA256_TAR} ${TAR_NAME}" > "/tmp/${TAR_NAME}.sha256"
|
||||||
|
|
||||||
|
# -- Upload packages + checksums to release tag --------------------
|
||||||
|
for ASSET in "${ZIP_NAME}" "${TAR_NAME}" "${ZIP_NAME}.sha256" "${TAR_NAME}.sha256"; do
|
||||||
|
[ ! -f "/tmp/${ASSET}" ] && continue
|
||||||
|
# Delete existing asset with same name
|
||||||
ASSET_ID=$(echo "$ASSETS" | python3 -c "
|
ASSET_ID=$(echo "$ASSETS" | python3 -c "
|
||||||
import sys,json
|
import sys,json
|
||||||
assets = json.load(sys.stdin)
|
assets = json.load(sys.stdin)
|
||||||
for a in assets:
|
for a in assets:
|
||||||
if a['name'] == '${ASSET_NAME}':
|
if a['name'] == '${ASSET}':
|
||||||
print(a['id']); break
|
print(a['id']); break
|
||||||
" 2>/dev/null || true)
|
" 2>/dev/null || true)
|
||||||
if [ -n "$ASSET_ID" ]; then
|
[ -n "$ASSET_ID" ] && curl -sf -X DELETE -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
||||||
curl -sf -X DELETE -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
"${API_BASE}/releases/${RELEASE_ID}/assets/${ASSET_ID}" 2>/dev/null || true
|
||||||
"${API_BASE}/releases/${RELEASE_ID}/assets/${ASSET_ID}" 2>/dev/null || true
|
# Upload
|
||||||
fi
|
curl -sf -X POST -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
||||||
|
-H "Content-Type: application/octet-stream" \
|
||||||
|
--data-binary @"/tmp/${ASSET}" \
|
||||||
|
"${API_BASE}/releases/${RELEASE_ID}/assets?name=${ASSET}" > /dev/null 2>&1 || true
|
||||||
done
|
done
|
||||||
|
|
||||||
# -- Upload both to release tag ----------------------------------
|
# updates.xml already handled by Step 5 (updates_xml_build.php with preserve logic)
|
||||||
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="${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}"
|
|
||||||
|
|
||||||
# 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"
|
|
||||||
" </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="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>" || true
|
|
||||||
git push || true
|
|
||||||
|
|
||||||
# Sync updates.xml to main via direct API (always runs — may be on version/XX branch)
|
|
||||||
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: sync updates.xml ${VERSION} [skip ci]" \
|
|
||||||
--arg branch "main" \
|
|
||||||
'{content: $content, sha: $sha, message: $msg, branch: $branch}'
|
|
||||||
)" > /dev/null 2>&1 \
|
|
||||||
&& echo "updates.xml synced to main via API" \
|
|
||||||
|| echo "WARNING: failed to sync updates.xml to main"
|
|
||||||
else
|
|
||||||
echo "WARNING: could not get updates.xml SHA from main"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "### Packages" >> $GITHUB_STEP_SUMMARY
|
echo "### Packages" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
@@ -556,72 +500,33 @@ jobs:
|
|||||||
echo "| Release | \`${RELEASE_TAG}\` | |" >> $GITHUB_STEP_SUMMARY
|
echo "| Release | \`${RELEASE_TAG}\` | |" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "| Download | [${ZIP_NAME}](${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/${RELEASE_TAG}/${ZIP_NAME}) |" >> $GITHUB_STEP_SUMMARY
|
echo "| Download | [${ZIP_NAME}](${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/${RELEASE_TAG}/${ZIP_NAME}) |" >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
# -- STEP 8b: Update release description with changelog + SHA ----------------
|
# -- STEP 8b: Update release description with changelog ----------------------
|
||||||
- name: "Step 8b: Update release body with changelog and SHA"
|
- name: "Step 8b: Update release body"
|
||||||
if: steps.version.outputs.skip != 'true'
|
if: steps.version.outputs.skip != 'true'
|
||||||
run: |
|
run: |
|
||||||
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||||
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
|
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
|
||||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
MOKO_CLI="/tmp/moko-platform-api/cli"
|
||||||
EXT_ELEMENT="${{ steps.updates.outputs.ext_element }}"
|
|
||||||
EXT_TYPE="${{ steps.updates.outputs.ext_type }}"
|
|
||||||
EXT_FOLDER="${{ steps.updates.outputs.ext_folder }}"
|
|
||||||
|
|
||||||
# Build TYPE_PREFIX to match Step 8's ZIP naming
|
php ${MOKO_CLI}/release_body_update.php \
|
||||||
TYPE_PREFIX=""
|
--path . --version "${VERSION}" --tag "${RELEASE_TAG}" \
|
||||||
case "${EXT_TYPE}" in
|
--token "${{ secrets.GA_TOKEN }}" \
|
||||||
plugin) TYPE_PREFIX="plg_${EXT_FOLDER}_" ;;
|
--gitea-url "${GITEA_URL}" --org "${GITEA_ORG}" --repo "${GITEA_REPO}" \
|
||||||
module) TYPE_PREFIX="mod_" ;;
|
2>/dev/null || {
|
||||||
component) TYPE_PREFIX="com_" ;;
|
# Fallback: simple body update if CLI not available
|
||||||
template) TYPE_PREFIX="tpl_" ;;
|
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||||
library) TYPE_PREFIX="lib_" ;;
|
RELEASE_ID=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
||||||
package) TYPE_PREFIX="pkg_" ;;
|
"${API_BASE}/releases/tags/${RELEASE_TAG}" 2>/dev/null | \
|
||||||
esac
|
python3 -c "import sys,json; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
|
||||||
ZIP_NAME="${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION}.zip"
|
if [ -n "$RELEASE_ID" ] && [ "$RELEASE_ID" != "None" ]; then
|
||||||
TAR_NAME="${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION}.tar.gz"
|
BODY="## ${VERSION} ($(date +%Y-%m-%d))\n\nChecksum files attached as \`*.sha256\` assets."
|
||||||
|
curl -sf -X PATCH -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
||||||
# Get SHA from the built files
|
-H "Content-Type: application/json" \
|
||||||
SHA256_ZIP=""
|
"${API_BASE}/releases/${RELEASE_ID}" \
|
||||||
[ -f "/tmp/${ZIP_NAME}" ] && SHA256_ZIP=$(sha256sum "/tmp/${ZIP_NAME}" | cut -d' ' -f1)
|
-d "{\"body\":\"${BODY}\"}" > /dev/null 2>&1
|
||||||
SHA256_TAR=""
|
fi
|
||||||
[ -f "/tmp/${TAR_NAME}" ] && SHA256_TAR=$(sha256sum "/tmp/${TAR_NAME}" | cut -d' ' -f1)
|
}
|
||||||
|
echo "Release body updated" >> $GITHUB_STEP_SUMMARY
|
||||||
# Extract latest changelog entry (strip the ## header to avoid duplicate)
|
|
||||||
CHANGELOG=""
|
|
||||||
if [ -f "CHANGELOG.md" ]; then
|
|
||||||
CHANGELOG=$(sed -n "/^## \[*${VERSION}/,/^## \[*[0-9]/p" CHANGELOG.md | sed '$d' | sed '1d')
|
|
||||||
[ -z "$CHANGELOG" ] && CHANGELOG=$(sed -n '/^## /,/^## /p' CHANGELOG.md | sed '$d' | sed '1d' | head -30)
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Build release body (single header, no duplicate from changelog)
|
|
||||||
BODY="## ${VERSION} ($(date +%Y-%m-%d))\n\n"
|
|
||||||
if [ -n "$CHANGELOG" ]; then
|
|
||||||
BODY="${BODY}${CHANGELOG}\n\n"
|
|
||||||
fi
|
|
||||||
BODY="${BODY}---\n\n### Checksums\n\n"
|
|
||||||
BODY="${BODY}| File | SHA-256 |\n|------|--------|\n"
|
|
||||||
[ -n "$SHA256_ZIP" ] && BODY="${BODY}| \`${ZIP_NAME}\` | \`${SHA256_ZIP}\` |\n"
|
|
||||||
[ -n "$SHA256_TAR" ] && BODY="${BODY}| \`${TAR_NAME}\` | \`${SHA256_TAR}\` |\n"
|
|
||||||
|
|
||||||
# Get release ID and update body
|
|
||||||
RELEASE_ID=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
|
|
||||||
"${API_BASE}/releases/tags/${RELEASE_TAG}" 2>/dev/null | \
|
|
||||||
python3 -c "import sys,json; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
|
|
||||||
|
|
||||||
if [ -n "$RELEASE_ID" ] && [ "$RELEASE_ID" != "None" ]; then
|
|
||||||
python3 -c "
|
|
||||||
import json, urllib.request
|
|
||||||
body = '''$(printf '%b' "$BODY")'''
|
|
||||||
data = json.dumps({'body': body}).encode()
|
|
||||||
req = urllib.request.Request(
|
|
||||||
'${API_BASE}/releases/${RELEASE_ID}',
|
|
||||||
data=data,
|
|
||||||
headers={'Authorization': 'token ${{ secrets.GA_TOKEN }}', 'Content-Type': 'application/json'},
|
|
||||||
method='PATCH'
|
|
||||||
)
|
|
||||||
urllib.request.urlopen(req)
|
|
||||||
" 2>/dev/null && echo "Release body updated with changelog + SHA" >> $GITHUB_STEP_SUMMARY
|
|
||||||
fi
|
|
||||||
|
|
||||||
# -- STEP 9: Mirror to GitHub (stable only) --------------------------------
|
# -- STEP 9: Mirror to GitHub (stable only) --------------------------------
|
||||||
- name: "Step 9: Mirror release to GitHub"
|
- name: "Step 9: Mirror release to GitHub"
|
||||||
|
|||||||
@@ -107,6 +107,9 @@ jobs:
|
|||||||
php ${MOKO_CLI}/version_set_platform.php \
|
php ${MOKO_CLI}/version_set_platform.php \
|
||||||
--path . --version "$VERSION" --branch "${{ github.ref_name }}" 2>/dev/null || true
|
--path . --version "$VERSION" --branch "${{ github.ref_name }}" 2>/dev/null || true
|
||||||
|
|
||||||
|
# Verify version consistency across all files
|
||||||
|
php ${MOKO_CLI}/version_check.php --path . --fix 2>/dev/null || true
|
||||||
|
|
||||||
# Commit version bump
|
# Commit version bump
|
||||||
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
||||||
git config --local user.name "gitea-actions[bot]"
|
git config --local user.name "gitea-actions[bot]"
|
||||||
@@ -177,6 +180,8 @@ jobs:
|
|||||||
|
|
||||||
mkdir -p build/package
|
mkdir -p build/package
|
||||||
|
|
||||||
|
REPO_ROOT=$(pwd)
|
||||||
|
|
||||||
if [ "$EXT_TYPE" = "package" ] && [ -d "${SOURCE_DIR}/packages" ]; then
|
if [ "$EXT_TYPE" = "package" ] && [ -d "${SOURCE_DIR}/packages" ]; then
|
||||||
echo "=== Building Joomla PACKAGE (multi-extension) ==="
|
echo "=== Building Joomla PACKAGE (multi-extension) ==="
|
||||||
for ext_dir in "${SOURCE_DIR}"/packages/*/; do
|
for ext_dir in "${SOURCE_DIR}"/packages/*/; do
|
||||||
@@ -184,8 +189,8 @@ jobs:
|
|||||||
EXT_NAME=$(basename "$ext_dir")
|
EXT_NAME=$(basename "$ext_dir")
|
||||||
echo " Packaging sub-extension: ${EXT_NAME}"
|
echo " Packaging sub-extension: ${EXT_NAME}"
|
||||||
cd "$ext_dir"
|
cd "$ext_dir"
|
||||||
zip -r "../../build/package/${EXT_NAME}.zip" . -x $EXCLUDES
|
zip -r "${REPO_ROOT}/build/package/${EXT_NAME}.zip" . -x $EXCLUDES
|
||||||
cd "$OLDPWD"
|
cd "${REPO_ROOT}"
|
||||||
done
|
done
|
||||||
for f in "${SOURCE_DIR}"/*.xml "${SOURCE_DIR}"/*.php; do
|
for f in "${SOURCE_DIR}"/*.xml "${SOURCE_DIR}"/*.php; do
|
||||||
[ -f "$f" ] && cp "$f" build/package/
|
[ -f "$f" ] && cp "$f" build/package/
|
||||||
@@ -231,7 +236,7 @@ jobs:
|
|||||||
|
|
||||||
BODY="## ${VERSION} ($(date +%Y-%m-%d))
|
BODY="## ${VERSION} ($(date +%Y-%m-%d))
|
||||||
**Channel:** ${STABILITY}
|
**Channel:** ${STABILITY}
|
||||||
**SHA-256:** \`${SHA256}\`"
|
Checksum file attached as \`${ZIP_NAME}.sha256\`."
|
||||||
|
|
||||||
# Delete existing release
|
# Delete existing release
|
||||||
EXISTING_ID=$(curl -sS -H "Authorization: token ${TOKEN}" \
|
EXISTING_ID=$(curl -sS -H "Authorization: token ${TOKEN}" \
|
||||||
@@ -263,6 +268,13 @@ jobs:
|
|||||||
"${API}/releases/${RELEASE_ID}/assets?name=${ZIP_NAME}" \
|
"${API}/releases/${RELEASE_ID}/assets?name=${ZIP_NAME}" \
|
||||||
--data-binary "@build/${ZIP_NAME}"
|
--data-binary "@build/${ZIP_NAME}"
|
||||||
|
|
||||||
|
# Upload per-file checksum
|
||||||
|
echo "${SHA256} ${ZIP_NAME}" > "build/${ZIP_NAME}.sha256"
|
||||||
|
curl -sS -X POST -H "Authorization: token ${TOKEN}" \
|
||||||
|
-H "Content-Type: application/octet-stream" \
|
||||||
|
"${API}/releases/${RELEASE_ID}/assets?name=${ZIP_NAME}.sha256" \
|
||||||
|
--data-binary "@build/${ZIP_NAME}.sha256"
|
||||||
|
|
||||||
echo "Released: ${EXT_ELEMENT} ${VERSION} (${STABILITY})"
|
echo "Released: ${EXT_ELEMENT} ${VERSION} (${STABILITY})"
|
||||||
|
|
||||||
- name: Update updates.xml
|
- name: Update updates.xml
|
||||||
@@ -279,43 +291,17 @@ jobs:
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Map stability to XML tag name
|
# Use moko-platform CLI to build/update updates.xml (preserves other channels)
|
||||||
case "$STABILITY" in
|
MOKO_CLI="/tmp/moko-platform-api/cli"
|
||||||
development) XML_TAG="development" ;;
|
if [ -f "${MOKO_CLI}/updates_xml_build.php" ]; then
|
||||||
alpha) XML_TAG="alpha" ;;
|
php "${MOKO_CLI}/updates_xml_build.php" \
|
||||||
beta) XML_TAG="beta" ;;
|
--path . --version "${VERSION}" --stability "${STABILITY}" \
|
||||||
release-candidate) XML_TAG="rc" ;;
|
--sha "${SHA256}" \
|
||||||
*) XML_TAG="$STABILITY" ;;
|
--gitea-url "${GITEA_URL}" --org "${GITEA_ORG}" --repo "${GITEA_REPO}"
|
||||||
esac
|
echo "Updated ${STABILITY} channel via CLI: version=${VERSION}"
|
||||||
|
else
|
||||||
DOWNLOAD_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/${TAG}/${ZIP_NAME}"
|
echo "WARNING: updates_xml_build.php not found — skipping"
|
||||||
|
fi
|
||||||
# Use PHP to update the channel in updates.xml
|
|
||||||
php -r '
|
|
||||||
$xml_tag = $argv[1];
|
|
||||||
$version = $argv[2];
|
|
||||||
$sha256 = $argv[3];
|
|
||||||
$url = $argv[4];
|
|
||||||
$date = date("Y-m-d");
|
|
||||||
|
|
||||||
$content = file_get_contents("updates.xml");
|
|
||||||
$pattern = "/(<update>(?:(?!<\/update>).)*?<tag>" . preg_quote($xml_tag) . "<\/tag>.*?<\/update>)/s";
|
|
||||||
|
|
||||||
$content = preg_replace_callback($pattern, function($m) use ($version, $sha256, $url, $date) {
|
|
||||||
$block = $m[0];
|
|
||||||
$block = preg_replace("/<version>[^<]*<\/version>/", "<version>{$version}</version>", $block);
|
|
||||||
if (strpos($block, "<sha256>") !== false) {
|
|
||||||
$block = preg_replace("/<sha256>[^<]*<\/sha256>/", "<sha256>{$sha256}</sha256>", $block);
|
|
||||||
} else {
|
|
||||||
$block = str_replace("</downloads>", "</downloads>\n <sha256>{$sha256}</sha256>", $block);
|
|
||||||
}
|
|
||||||
$block = preg_replace("/(<downloadurl[^>]*>)[^<]*(<\/downloadurl>)/", "\${1}{$url}\${2}", $block);
|
|
||||||
return $block;
|
|
||||||
}, $content);
|
|
||||||
|
|
||||||
file_put_contents("updates.xml", $content);
|
|
||||||
echo "Updated {$xml_tag} channel: version={$version}\n";
|
|
||||||
' "$XML_TAG" "$VERSION" "$SHA256" "$DOWNLOAD_URL"
|
|
||||||
|
|
||||||
# Commit and push
|
# Commit and push
|
||||||
if ! git diff --quiet updates.xml 2>/dev/null; then
|
if ! git diff --quiet updates.xml 2>/dev/null; then
|
||||||
|
|||||||
@@ -42,6 +42,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Install API endpoint: extract ZIP to temp directory before passing to Joomla Installer (was passing ZIP path directly)
|
- Install API endpoint: extract ZIP to temp directory before passing to Joomla Installer (was passing ZIP path directly)
|
||||||
- Clean up extracted temp directory on success or failure
|
- Clean up extracted temp directory on success or failure
|
||||||
- Update site disabled by Joomla when protected=1 — ensureProtectedFlag() now re-enables it
|
- Update site disabled by Joomla when protected=1 — ensureProtectedFlag() now re-enables it
|
||||||
|
- CI: auto-release fetches updates.xml from main before building (preserves all channels)
|
||||||
|
- CI: version_check.php --fix runs after version bump in both workflows
|
||||||
|
- CI: checksums attached as `[filename].sha256` files instead of in release body
|
||||||
|
- CI: auto-release cleaned up — removed duplicate asset loops, inline Python updater, dead code
|
||||||
|
- CI: Step 8b uses `release_body_update.php` CLI instead of inline Python
|
||||||
|
- CI: Step 6 tag creation no longer gated by `is_minor` (was never set)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- CI: auto-release uses stream tag `stable` instead of version tag `vXX`
|
- CI: auto-release uses stream tag `stable` instead of version tag `vXX`
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
DEFGROUP: Joomla.Plugin
|
DEFGROUP: Joomla.Plugin
|
||||||
INGROUP: MokoWaaS
|
INGROUP: MokoWaaS
|
||||||
REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS
|
REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS
|
||||||
VERSION: 02.06.04
|
VERSION: 02.08.03
|
||||||
PATH: /README.md
|
PATH: /README.md
|
||||||
BRIEF: MokoWaaS platform plugin for Joomla
|
BRIEF: MokoWaaS platform plugin for Joomla
|
||||||
-->
|
-->
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<license>GPL-3.0-or-later</license>
|
<license>GPL-3.0-or-later</license>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||||
<version>02.06.04</version>
|
<version>02.08.03</version>
|
||||||
<description>Minimal API-only component for MokoWaaS. Provides REST endpoints for site health, cache, updates, and backups.</description>
|
<description>Minimal API-only component for MokoWaaS. Provides REST endpoints for site health, cache, updates, and backups.</description>
|
||||||
<namespace path="api/src">Moko\Component\MokoWaaS\Api</namespace>
|
<namespace path="api/src">Moko\Component\MokoWaaS\Api</namespace>
|
||||||
<administration>
|
<administration>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
<license>GNU General Public License version 3 or later; see LICENSE.md</license>
|
<license>GNU General Public License version 3 or later; see LICENSE.md</license>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||||
<version>02.06.04</version>
|
<version>02.08.03</version>
|
||||||
<description>This plugin rebrands the Joomla system interface with MokoWaaS identity. It applies language overrides and ensures consistent branding across the platform.</description>
|
<description>This plugin rebrands the Joomla system interface with MokoWaaS identity. It applies language overrides and ensures consistent branding across the platform.</description>
|
||||||
<namespace path=".">Moko\Plugin\System\MokoWaaS</namespace>
|
<namespace path=".">Moko\Plugin\System\MokoWaaS</namespace>
|
||||||
<scriptfile>script.php</scriptfile>
|
<scriptfile>script.php</scriptfile>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<license>GPL-3.0-or-later</license>
|
<license>GPL-3.0-or-later</license>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||||
<version>02.06.04</version>
|
<version>02.08.03</version>
|
||||||
<description>Joomla Web Services API routes for MokoWaaS site management — health checks, cache, updates, backups, and site info.</description>
|
<description>Joomla Web Services API routes for MokoWaaS site management — health checks, cache, updates, backups, and site info.</description>
|
||||||
<namespace path="src">Moko\Plugin\WebServices\MokoWaaS</namespace>
|
<namespace path="src">Moko\Plugin\WebServices\MokoWaaS</namespace>
|
||||||
<files>
|
<files>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<extension type="package" method="upgrade">
|
<extension type="package" method="upgrade">
|
||||||
<name>MokoWaaS</name>
|
<name>MokoWaaS</name>
|
||||||
<packagename>mokowaas</packagename>
|
<packagename>mokowaas</packagename>
|
||||||
<version>02.06.04</version>
|
<version>02.08.03</version>
|
||||||
<creationDate>2026-05-23</creationDate>
|
<creationDate>2026-05-23</creationDate>
|
||||||
<author>Moko Consulting</author>
|
<author>Moko Consulting</author>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
|
|||||||
Reference in New Issue
Block a user