Template
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 06be39d2d9 | |||
| 1d7b38961f | |||
| 8b1945aabc | |||
| ff1c7a4815 | |||
| 2419912d1d | |||
| 15b2656bcc | |||
| 295b436a87 | |||
| f8e9afe298 |
File diff suppressed because it is too large
Load Diff
@@ -1,386 +0,0 @@
|
|||||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
#
|
|
||||||
# FILE INFORMATION
|
|
||||||
# DEFGROUP: Gitea.Workflow
|
|
||||||
# INGROUP: MokoStandards.Release
|
|
||||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards
|
|
||||||
# PATH: /templates/workflows/universal/pre-release.yml.template
|
|
||||||
# VERSION: 05.00.00
|
|
||||||
# BRIEF: Manual pre-release — builds dev/alpha/beta/rc packages from any branch
|
|
||||||
|
|
||||||
name: "Universal: Pre-Release"
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
stability:
|
|
||||||
description: 'Pre-release channel'
|
|
||||||
required: true
|
|
||||||
type: choice
|
|
||||||
options:
|
|
||||||
- development
|
|
||||||
- alpha
|
|
||||||
- beta
|
|
||||||
- release-candidate
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
env:
|
|
||||||
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 }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
name: "Build Pre-Release (${{ inputs.stability }})"
|
|
||||||
runs-on: release
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
token: ${{ secrets.GA_TOKEN }}
|
|
||||||
|
|
||||||
- name: Setup PHP
|
|
||||||
run: |
|
|
||||||
if ! command -v php &> /dev/null; then
|
|
||||||
sudo apt-get update -qq
|
|
||||||
sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip >/dev/null 2>&1
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Detect platform
|
|
||||||
id: platform
|
|
||||||
run: |
|
|
||||||
# Parse .manifest.xml via manifest_read.php — outputs all fields to GITHUB_OUTPUT
|
|
||||||
php /tmp/mokostandards-api/cli/manifest_read.php --path . --github-output 2>/dev/null || true
|
|
||||||
PLATFORM=$(php /tmp/mokostandards-api/cli/manifest_read.php --path . --field platform 2>/dev/null)
|
|
||||||
[ -z "$PLATFORM" ] && PLATFORM="generic"
|
|
||||||
echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT"
|
|
||||||
# entry-point from manifest, find as fallback
|
|
||||||
MOD_FILE=$(php /tmp/mokostandards-api/cli/manifest_read.php --path . --field entry-point 2>/dev/null)
|
|
||||||
[ -z "$MOD_FILE" ] && MOD_FILE=$(find . -maxdepth 4 -name "mod*.class.php" ! -path "./.git/*" -exec grep -l 'extends DolibarrModules' {} \; 2>/dev/null | head -1)
|
|
||||||
MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
|
|
||||||
echo "manifest=${MANIFEST}" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "mod_file=${MOD_FILE}" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
- name: Resolve metadata
|
|
||||||
id: meta
|
|
||||||
run: |
|
|
||||||
STABILITY="${{ inputs.stability }}"
|
|
||||||
|
|
||||||
case "$STABILITY" in
|
|
||||||
development) SUFFIX="-dev"; TAG="development" ;;
|
|
||||||
alpha) SUFFIX="-alpha"; TAG="alpha" ;;
|
|
||||||
beta) SUFFIX="-beta"; TAG="beta" ;;
|
|
||||||
release-candidate) SUFFIX="-rc"; TAG="release-candidate" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Read and bump patch version (with rollover)
|
|
||||||
CURRENT=$(sed -n 's/.*VERSION:[[:space:]]*\([0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\).*/\1/p' README.md 2>/dev/null | head -1)
|
|
||||||
[ -z "$CURRENT" ] && CURRENT="00.00.00"
|
|
||||||
|
|
||||||
MAJOR=$(echo "$CURRENT" | cut -d. -f1)
|
|
||||||
MINOR=$(echo "$CURRENT" | cut -d. -f2)
|
|
||||||
PATCH=$(echo "$CURRENT" | cut -d. -f3)
|
|
||||||
|
|
||||||
# Patch bump with rollover: ZZ=99 → bump minor, YY=99 → bump major
|
|
||||||
NEW_PATCH=$((10#$PATCH + 1))
|
|
||||||
NEW_MINOR=$((10#$MINOR))
|
|
||||||
NEW_MAJOR=$((10#$MAJOR))
|
|
||||||
|
|
||||||
if [ $NEW_PATCH -gt 99 ]; then
|
|
||||||
NEW_PATCH=0
|
|
||||||
NEW_MINOR=$((NEW_MINOR + 1))
|
|
||||||
fi
|
|
||||||
if [ $NEW_MINOR -gt 99 ]; then
|
|
||||||
NEW_MINOR=0
|
|
||||||
NEW_MAJOR=$((NEW_MAJOR + 1))
|
|
||||||
fi
|
|
||||||
|
|
||||||
VERSION=$(printf "%02d.%02d.%02d" $NEW_MAJOR $NEW_MINOR $NEW_PATCH)
|
|
||||||
TODAY=$(date +%Y-%m-%d)
|
|
||||||
|
|
||||||
echo "Bumping: ${CURRENT} → ${VERSION} (patch)"
|
|
||||||
|
|
||||||
# Update README.md
|
|
||||||
sed -i "s/VERSION:[[:space:]]*${CURRENT}/VERSION: ${VERSION}/" README.md
|
|
||||||
|
|
||||||
# Update platform-specific manifest
|
|
||||||
PLATFORM="${{ steps.platform.outputs.platform }}"
|
|
||||||
MANIFEST="${{ steps.platform.outputs.manifest }}"
|
|
||||||
MOD_FILE="${{ steps.platform.outputs.mod_file }}"
|
|
||||||
case "$PLATFORM" in
|
|
||||||
joomla)
|
|
||||||
if [ -n "$MANIFEST" ]; then
|
|
||||||
MANIFEST_VER=$(sed -n 's/.*<version>\([^<]*\)<\/version>.*/\1/p' "$MANIFEST" | head -1)
|
|
||||||
sed -i "s|<version>${MANIFEST_VER}</version>|<version>${VERSION}</version>|" "$MANIFEST"
|
|
||||||
sed -i "s|<creationDate>[^<]*</creationDate>|<creationDate>${TODAY}</creationDate>|" "$MANIFEST"
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
dolibarr)
|
|
||||||
if [ -n "$MOD_FILE" ]; then
|
|
||||||
sed -i "s/\$this->version = '[^']*'/\$this->version = '${VERSION}'/" "$MOD_FILE"
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
*) ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Commit version bump
|
|
||||||
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
|
||||||
git config --local user.name "gitea-actions[bot]"
|
|
||||||
git remote set-url origin "https://jmiller:${{ secrets.GA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
|
||||||
git add -A
|
|
||||||
git diff --cached --quiet || {
|
|
||||||
git commit -m "chore(version): bump ${CURRENT} → ${VERSION} [skip ci]"
|
|
||||||
git push origin HEAD 2>&1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Auto-detect element (platform-aware)
|
|
||||||
case "$PLATFORM" in
|
|
||||||
joomla)
|
|
||||||
MANIFEST="${{ steps.platform.outputs.manifest }}"
|
|
||||||
EXT_ELEMENT=""
|
|
||||||
if [ -n "$MANIFEST" ]; then
|
|
||||||
EXT_ELEMENT=$(sed -n 's/.*<element>\([^<]*\)<\/element>.*/\1/p' "$MANIFEST" 2>/dev/null | head -1)
|
|
||||||
if [ -z "$EXT_ELEMENT" ]; then
|
|
||||||
EXT_ELEMENT=$(basename "$MANIFEST" .xml | tr '[:upper:]' '[:lower:]')
|
|
||||||
case "$EXT_ELEMENT" in
|
|
||||||
templatedetails|manifest) EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -') ;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
dolibarr)
|
|
||||||
MOD_FILE="${{ steps.platform.outputs.mod_file }}"
|
|
||||||
if [ -n "$MOD_FILE" ]; then
|
|
||||||
MOD_BASENAME=$(basename "$MOD_FILE" .class.php)
|
|
||||||
EXT_ELEMENT=$(echo "$MOD_BASENAME" | sed 's/^mod//' | tr '[:upper:]' '[:lower:]')
|
|
||||||
else
|
|
||||||
EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
ZIP_NAME="${EXT_ELEMENT}-${VERSION}${SUFFIX}.zip"
|
|
||||||
|
|
||||||
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "stability=${STABILITY}" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "suffix=${SUFFIX}" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "zip_name=${ZIP_NAME}" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "ext_element=${EXT_ELEMENT}" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "manifest=${MANIFEST}" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
echo "=== Pre-Release: ${EXT_ELEMENT} ${VERSION}${SUFFIX} ==="
|
|
||||||
|
|
||||||
- name: Build package
|
|
||||||
run: |
|
|
||||||
SOURCE_DIR="src"
|
|
||||||
[ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs"
|
|
||||||
if [ ! -d "$SOURCE_DIR" ]; then
|
|
||||||
echo "::error::No src/ or htdocs/ directory"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
mkdir -p build/package
|
|
||||||
rsync -a \
|
|
||||||
--exclude='sftp-config*' \
|
|
||||||
--exclude='.ftpignore' \
|
|
||||||
--exclude='*.ppk' \
|
|
||||||
--exclude='*.pem' \
|
|
||||||
--exclude='*.key' \
|
|
||||||
--exclude='.env*' \
|
|
||||||
--exclude='*.local' \
|
|
||||||
--exclude='.build-trigger' \
|
|
||||||
"${SOURCE_DIR}/" build/package/
|
|
||||||
|
|
||||||
- name: Create ZIP
|
|
||||||
id: zip
|
|
||||||
run: |
|
|
||||||
ZIP_NAME="${{ steps.meta.outputs.zip_name }}"
|
|
||||||
cd build/package
|
|
||||||
zip -r "../${ZIP_NAME}" .
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
SHA256=$(sha256sum "${ZIP_NAME}" | cut -d' ' -f1)
|
|
||||||
echo "sha256=${SHA256}" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "ZIP: ${ZIP_NAME} (SHA: ${SHA256:0:16}...)"
|
|
||||||
|
|
||||||
- name: Create or replace Gitea release
|
|
||||||
id: release
|
|
||||||
run: |
|
|
||||||
TAG="${{ steps.meta.outputs.tag }}"
|
|
||||||
VERSION="${{ steps.meta.outputs.version }}"
|
|
||||||
STABILITY="${{ steps.meta.outputs.stability }}"
|
|
||||||
SHA256="${{ steps.zip.outputs.sha256 }}"
|
|
||||||
ZIP_NAME="${{ steps.meta.outputs.zip_name }}"
|
|
||||||
EXT_ELEMENT="${{ steps.meta.outputs.ext_element }}"
|
|
||||||
TOKEN="${{ secrets.GA_TOKEN }}"
|
|
||||||
API="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
|
||||||
BRANCH=$(git branch --show-current)
|
|
||||||
|
|
||||||
BODY="## ${VERSION} ($(date +%Y-%m-%d))
|
|
||||||
**Channel:** ${STABILITY}
|
|
||||||
**SHA-256:** \`${SHA256}\`"
|
|
||||||
|
|
||||||
# Delete existing release
|
|
||||||
EXISTING_ID=$(curl -sS -H "Authorization: token ${TOKEN}" \
|
|
||||||
"${API}/releases/tags/${TAG}" | jq -r '.id // empty' 2>/dev/null)
|
|
||||||
if [ -n "$EXISTING_ID" ]; then
|
|
||||||
curl -sS -X DELETE -H "Authorization: token ${TOKEN}" \
|
|
||||||
"${API}/releases/${EXISTING_ID}" 2>/dev/null || true
|
|
||||||
curl -sS -X DELETE -H "Authorization: token ${TOKEN}" \
|
|
||||||
"${API}/tags/${TAG}" 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create release
|
|
||||||
RELEASE_ID=$(curl -sS -X POST -H "Authorization: token ${TOKEN}" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
"${API}/releases" \
|
|
||||||
-d "$(jq -n \
|
|
||||||
--arg tag "$TAG" \
|
|
||||||
--arg target "$BRANCH" \
|
|
||||||
--arg name "${EXT_ELEMENT} ${VERSION} (${STABILITY})" \
|
|
||||||
--arg body "$BODY" \
|
|
||||||
'{tag_name: $tag, target_commitish: $target, name: $name, body: $body, prerelease: true}'
|
|
||||||
)" | jq -r '.id')
|
|
||||||
|
|
||||||
echo "release_id=${RELEASE_ID}" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
# Upload ZIP
|
|
||||||
curl -sS -X POST -H "Authorization: token ${TOKEN}" \
|
|
||||||
-H "Content-Type: application/octet-stream" \
|
|
||||||
"${API}/releases/${RELEASE_ID}/assets?name=${ZIP_NAME}" \
|
|
||||||
--data-binary "@build/${ZIP_NAME}"
|
|
||||||
|
|
||||||
echo "Released: ${EXT_ELEMENT} ${VERSION} (${STABILITY})"
|
|
||||||
|
|
||||||
- name: Update updates.xml
|
|
||||||
if: steps.platform.outputs.platform == 'joomla'
|
|
||||||
run: |
|
|
||||||
STABILITY="${{ steps.meta.outputs.stability }}"
|
|
||||||
VERSION="${{ steps.meta.outputs.version }}"
|
|
||||||
SHA256="${{ steps.zip.outputs.sha256 }}"
|
|
||||||
ZIP_NAME="${{ steps.meta.outputs.zip_name }}"
|
|
||||||
TAG="${{ steps.meta.outputs.tag }}"
|
|
||||||
DATE=$(date +%Y-%m-%d)
|
|
||||||
|
|
||||||
if [ ! -f "updates.xml" ]; then
|
|
||||||
echo "No updates.xml — skipping"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
export PY_STABILITY="$STABILITY" PY_VERSION="$VERSION" PY_SHA256="$SHA256" \
|
|
||||||
PY_ZIP_NAME="$ZIP_NAME" PY_TAG="$TAG" PY_DATE="$DATE" \
|
|
||||||
PY_GITEA_ORG="$GITEA_ORG" PY_GITEA_REPO="$GITEA_REPO"
|
|
||||||
python3 << 'PYEOF'
|
|
||||||
import re, os
|
|
||||||
|
|
||||||
stability = os.environ["PY_STABILITY"]
|
|
||||||
version = os.environ["PY_VERSION"]
|
|
||||||
sha256 = os.environ["PY_SHA256"]
|
|
||||||
zip_name = os.environ["PY_ZIP_NAME"]
|
|
||||||
tag = os.environ["PY_TAG"]
|
|
||||||
date = os.environ["PY_DATE"]
|
|
||||||
gitea_org = os.environ["PY_GITEA_ORG"]
|
|
||||||
gitea_repo = os.environ["PY_GITEA_REPO"]
|
|
||||||
download_url = f"https://git.mokoconsulting.tech/{gitea_org}/{gitea_repo}/releases/download/{tag}/{zip_name}"
|
|
||||||
|
|
||||||
with open("updates.xml", "r") as f:
|
|
||||||
content = f.read()
|
|
||||||
|
|
||||||
# Map stability to XML tag name
|
|
||||||
tag_map = {"development": "development", "alpha": "alpha", "beta": "beta", "release-candidate": "rc"}
|
|
||||||
xml_tag = tag_map.get(stability, stability)
|
|
||||||
|
|
||||||
pattern = r"(<update>(?:(?!</update>).)*?<tag>" + re.escape(xml_tag) + r"</tag>.*?</update>)"
|
|
||||||
match = re.search(pattern, content, re.DOTALL)
|
|
||||||
if match:
|
|
||||||
block = match.group(1)
|
|
||||||
updated = re.sub(r"<version>[^<]*</version>", f"<version>{version}</version>", block)
|
|
||||||
updated = re.sub(r"<creationDate>[^<]*</creationDate>", f"<creationDate>{date}</creationDate>", updated)
|
|
||||||
if "<sha256>" in updated:
|
|
||||||
updated = re.sub(r"<sha256>[^<]*</sha256>", f"<sha256>{sha256}</sha256>", updated)
|
|
||||||
else:
|
|
||||||
updated = updated.replace("</downloads>", f"</downloads>\n <sha256>{sha256}</sha256>")
|
|
||||||
updated = re.sub(r"(<downloadurl[^>]*>)[^<]*(</downloadurl>)", rf"\g<1>{download_url}\g<2>", updated)
|
|
||||||
content = content.replace(block, updated)
|
|
||||||
print(f"Updated {xml_tag} channel: version={version}")
|
|
||||||
else:
|
|
||||||
print(f"WARNING: No <tag>{xml_tag}</tag> block in updates.xml")
|
|
||||||
|
|
||||||
with open("updates.xml", "w") as f:
|
|
||||||
f.write(content)
|
|
||||||
PYEOF
|
|
||||||
|
|
||||||
# Commit and push to current branch
|
|
||||||
if ! git diff --quiet updates.xml 2>/dev/null; then
|
|
||||||
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
|
||||||
git config --local user.name "gitea-actions[bot]"
|
|
||||||
git add updates.xml
|
|
||||||
git commit -m "chore: update ${STABILITY} channel ${VERSION} [skip ci]"
|
|
||||||
git push origin HEAD 2>&1 || echo "WARNING: push failed"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: "Sync updates.xml to all branches"
|
|
||||||
if: steps.platform.outputs.platform == 'joomla'
|
|
||||||
run: |
|
|
||||||
CURRENT_BRANCH="${{ github.ref_name }}"
|
|
||||||
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
|
||||||
git config --local user.name "gitea-actions[bot]"
|
|
||||||
|
|
||||||
# Sync updates.xml to main and dev (whichever isn't current)
|
|
||||||
for BRANCH in main dev; do
|
|
||||||
[ "$BRANCH" = "$CURRENT_BRANCH" ] && continue
|
|
||||||
|
|
||||||
echo "Syncing updates.xml → ${BRANCH}"
|
|
||||||
git fetch origin "${BRANCH}" 2>/dev/null || continue
|
|
||||||
git checkout "origin/${BRANCH}" -- . 2>/dev/null || continue
|
|
||||||
git checkout "${CURRENT_BRANCH}" -- updates.xml
|
|
||||||
if ! git diff --quiet updates.xml 2>/dev/null; then
|
|
||||||
git add updates.xml
|
|
||||||
git commit -m "chore: sync updates.xml from ${CURRENT_BRANCH} [skip ci]"
|
|
||||||
git push origin HEAD:refs/heads/${BRANCH} 2>&1 || echo "WARNING: push to ${BRANCH} failed"
|
|
||||||
fi
|
|
||||||
git checkout "${CURRENT_BRANCH}" 2>/dev/null
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: "Delete lesser pre-release channels (cascade)"
|
|
||||||
continue-on-error: true
|
|
||||||
run: |
|
|
||||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
|
||||||
TOKEN="${{ secrets.GA_TOKEN }}"
|
|
||||||
STABILITY="${{ steps.meta.outputs.stability }}"
|
|
||||||
|
|
||||||
# Cascade: rc → beta,alpha,dev | beta → alpha,dev | alpha → dev | dev → nothing
|
|
||||||
case "$STABILITY" in
|
|
||||||
release-candidate) TAGS_TO_DELETE="beta alpha development" ;;
|
|
||||||
beta) TAGS_TO_DELETE="alpha development" ;;
|
|
||||||
alpha) TAGS_TO_DELETE="development" ;;
|
|
||||||
*) TAGS_TO_DELETE="" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
[ -z "$TAGS_TO_DELETE" ] && exit 0
|
|
||||||
|
|
||||||
for TAG in $TAGS_TO_DELETE; do
|
|
||||||
RELEASE_ID=$(curl -sS -H "Authorization: token ${TOKEN}" \
|
|
||||||
"${API_BASE}/releases/tags/${TAG}" 2>/dev/null | \
|
|
||||||
python3 -c "import sys,json; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
|
|
||||||
|
|
||||||
if [ -n "$RELEASE_ID" ] && [ "$RELEASE_ID" != "None" ]; then
|
|
||||||
curl -sS -X DELETE -H "Authorization: token ${TOKEN}" \
|
|
||||||
"${API_BASE}/releases/${RELEASE_ID}" 2>/dev/null || true
|
|
||||||
curl -sS -X DELETE -H "Authorization: token ${TOKEN}" \
|
|
||||||
"${API_BASE}/tags/${TAG}" 2>/dev/null || true
|
|
||||||
echo "Deleted: ${TAG} (id: ${RELEASE_ID})"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
@@ -0,0 +1,634 @@
|
|||||||
|
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
#
|
||||||
|
# FILE INFORMATION
|
||||||
|
# DEFGROUP: Gitea.Workflow
|
||||||
|
# INGROUP: moko-platform.Release
|
||||||
|
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/moko-platform
|
||||||
|
# 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. |
|
||||||
|
# | |
|
||||||
|
# | Platform-specific: |
|
||||||
|
# | joomla: XML manifest, updates.xml, type-prefixed packages |
|
||||||
|
# | dolibarr: mod*.class.php, update.txt, dev version reset |
|
||||||
|
# | generic: README-only, no update stream |
|
||||||
|
# | |
|
||||||
|
# +========================================================================+
|
||||||
|
|
||||||
|
name: "Universal: Build & Release"
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [closed]
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
paths:
|
||||||
|
- 'src/**'
|
||||||
|
- 'htdocs/**'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||||
|
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||||
|
GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }}
|
||||||
|
GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }}
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
name: Build & Release Pipeline
|
||||||
|
runs-on: release
|
||||||
|
if: >-
|
||||||
|
github.event.pull_request.merged == true || github.event_name == 'workflow_dispatch'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GA_TOKEN }}
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Setup moko-platform tools
|
||||||
|
env:
|
||||||
|
MOKO_CLONE_TOKEN: ${{ secrets.GA_TOKEN }}
|
||||||
|
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
||||||
|
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN }}"}}'
|
||||||
|
run: |
|
||||||
|
# Ensure PHP + Composer are available
|
||||||
|
if ! command -v composer &> /dev/null; 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
|
||||||
|
git clone --depth 1 --branch main --quiet \
|
||||||
|
"https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git" \
|
||||||
|
/tmp/moko-platform-api
|
||||||
|
cd /tmp/moko-platform-api
|
||||||
|
composer install --no-dev --no-interaction --quiet
|
||||||
|
|
||||||
|
|
||||||
|
# -- PLATFORM DETECTION ---------------------------------------------------
|
||||||
|
- name: Detect platform
|
||||||
|
id: platform
|
||||||
|
run: |
|
||||||
|
# Read platform from manifest.xml <platform> element; fallback to generic
|
||||||
|
PLATFORM=$(sed -n 's/.*<platform>\([^<]*\)<\/platform>.*//p' .mokogitea/manifest.xml 2>/dev/null | head -1 | tr -d '[:space:]')
|
||||||
|
[ -z "$PLATFORM" ] && PLATFORM="generic"
|
||||||
|
echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "Platform detected: ${PLATFORM}"
|
||||||
|
# For packages: prefer pkg_*.xml in src/; fallback to any manifest
|
||||||
|
MANIFEST=$(find ./src -maxdepth 1 -name "pkg_*.xml" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
|
||||||
|
[ -z "$MANIFEST" ] && MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" ! -path "*/packages/*" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
|
||||||
|
[ -z "$MANIFEST" ] && MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
|
||||||
|
MOD_FILE=$(find . -maxdepth 4 -name "mod*.class.php" ! -path "./.git/*" -exec grep -l 'extends DolibarrModules' {} \; 2>/dev/null | head -1)
|
||||||
|
echo "manifest=${MANIFEST}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "mod_file=${MOD_FILE}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
# -- STEP 1: Read version -----------------------------------------------
|
||||||
|
- name: "Step 1: Read version from README.md"
|
||||||
|
id: version
|
||||||
|
run: |
|
||||||
|
VERSION=$(php /tmp/moko-platform-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"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
# Derive major.minor for branch naming (patches update existing branch)
|
||||||
|
MINOR=$(echo "$VERSION" | awk -F. '{printf "%s.%s", $1, $2}')
|
||||||
|
PATCH=$(echo "$VERSION" | awk -F. '{print $3}')
|
||||||
|
|
||||||
|
MAJOR=$(echo "$VERSION" | awk -F. '{print $1}')
|
||||||
|
MINOR_NUM=$(echo "$VERSION" | awk -F. '{print $2}')
|
||||||
|
|
||||||
|
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "branch=version/${MAJOR}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "minor=$MINOR" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "major=$MAJOR" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "release_tag=stable" >> "$GITHUB_OUTPUT"
|
||||||
|
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 "is_minor=false" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "Version: $VERSION (patch — platform version + badges only)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# -- STEP 1b: Bump minor version (stable = minor bump, reset patch) ------
|
||||||
|
- name: "Step 1b: Bump minor version for stable release"
|
||||||
|
if: steps.version.outputs.skip != 'true'
|
||||||
|
id: bump
|
||||||
|
run: |
|
||||||
|
CLI="/tmp/moko-platform-api/cli"
|
||||||
|
CURRENT=$(php $CLI/version_read.php --path . 2>/dev/null)
|
||||||
|
[ -z "$CURRENT" ] && { echo "skip=true" >> "$GITHUB_OUTPUT"; exit 0; }
|
||||||
|
|
||||||
|
# Minor bump via CLI (updates README.md in-place)
|
||||||
|
BUMP_OUT=$(php $CLI/version_bump.php --path . --minor)
|
||||||
|
VERSION=$(php $CLI/version_read.php --path . 2>/dev/null)
|
||||||
|
TODAY=$(date +%Y-%m-%d)
|
||||||
|
echo "Stable bump: ${BUMP_OUT}"
|
||||||
|
|
||||||
|
# Set platform-specific version (Joomla XML, Dolibarr mod*.class.php)
|
||||||
|
php $CLI/version_set_platform.php --path . --version "$VERSION" --stability stable --branch main
|
||||||
|
|
||||||
|
# Promote [Unreleased] in CHANGELOG.md
|
||||||
|
php $CLI/changelog_promote.php --path . --version "$VERSION" --date "$TODAY" 2>/dev/null || true
|
||||||
|
|
||||||
|
# Commit and push
|
||||||
|
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
||||||
|
git config --local user.name "gitea-actions[bot]"
|
||||||
|
git remote set-url origin "https://jmiller:${{ secrets.GA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
||||||
|
git add -A
|
||||||
|
git diff --cached --quiet || {
|
||||||
|
git commit -m "chore(version): bump ${CURRENT} → ${VERSION} [skip ci]"
|
||||||
|
git push origin HEAD:main 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Override version output for rest of pipeline
|
||||||
|
MAJOR=$(echo "$VERSION" | cut -d. -f1)
|
||||||
|
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "major=${MAJOR}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Check if already released
|
||||||
|
if: steps.version.outputs.skip != 'true'
|
||||||
|
id: check
|
||||||
|
run: |
|
||||||
|
TAG="${{ steps.version.outputs.release_tag }}"
|
||||||
|
BRANCH="${{ steps.version.outputs.branch }}"
|
||||||
|
|
||||||
|
TAG_EXISTS=false
|
||||||
|
BRANCH_EXISTS=false
|
||||||
|
|
||||||
|
git rev-parse "$TAG" >/dev/null 2>&1 && TAG_EXISTS=true
|
||||||
|
git ls-remote --heads origin "$BRANCH" 2>/dev/null | grep -q "$BRANCH" && BRANCH_EXISTS=true
|
||||||
|
|
||||||
|
echo "tag_exists=$TAG_EXISTS" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "branch_exists=$BRANCH_EXISTS" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
# Tag and branch may persist across patch releases — never skip
|
||||||
|
echo "already_released=false" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
# -- SANITY CHECKS -------------------------------------------------------
|
||||||
|
- name: "Sanity: Pre-release validation"
|
||||||
|
if: >-
|
||||||
|
steps.version.outputs.skip != 'true' &&
|
||||||
|
steps.check.outputs.already_released != 'true'
|
||||||
|
run: |
|
||||||
|
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||||
|
ERRORS=0
|
||||||
|
|
||||||
|
PLATFORM="${{ steps.platform.outputs.platform }}"
|
||||||
|
MANIFEST="${{ steps.platform.outputs.manifest }}"
|
||||||
|
MOD_FILE="${{ steps.platform.outputs.mod_file }}"
|
||||||
|
echo "## Pre-Release Sanity Checks (${PLATFORM})" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
|
# -- Version drift check (must pass before release) --------
|
||||||
|
README_VER=$(sed -n 's/.*VERSION:[[:space:]]*\([0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\).*/\1/p' README.md 2>/dev/null | head -1)
|
||||||
|
if [ "$README_VER" != "$VERSION" ]; then
|
||||||
|
echo "- Version drift: README says \`${README_VER}\` but releasing \`${VERSION}\`" >> $GITHUB_STEP_SUMMARY
|
||||||
|
ERRORS=$((ERRORS+1))
|
||||||
|
else
|
||||||
|
echo "- Version consistent: \`${VERSION}\`" >> $GITHUB_STEP_SUMMARY
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check CHANGELOG version matches
|
||||||
|
CL_VER=$(sed -n 's/.*VERSION:[[:space:]]*\([0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\).*/\1/p' CHANGELOG.md 2>/dev/null | head -1)
|
||||||
|
if [ -n "$CL_VER" ] && [ "$CL_VER" != "$VERSION" ]; then
|
||||||
|
echo "- CHANGELOG drift: \`${CL_VER}\` != \`${VERSION}\`" >> $GITHUB_STEP_SUMMARY
|
||||||
|
ERRORS=$((ERRORS+1))
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check composer.json version if present
|
||||||
|
if [ -f "composer.json" ]; then
|
||||||
|
COMP_VER=$(sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' composer.json 2>/dev/null | head -1)
|
||||||
|
if [ -n "$COMP_VER" ] && [ "$COMP_VER" != "$VERSION" ]; then
|
||||||
|
echo "- composer.json drift: \`${COMP_VER}\` != \`${VERSION}\`" >> $GITHUB_STEP_SUMMARY
|
||||||
|
ERRORS=$((ERRORS+1))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Common checks
|
||||||
|
if [ ! -f "LICENSE" ]; then
|
||||||
|
echo "- Missing LICENSE file" >> $GITHUB_STEP_SUMMARY
|
||||||
|
ERRORS=$((ERRORS+1))
|
||||||
|
else
|
||||||
|
echo "- LICENSE present" >> $GITHUB_STEP_SUMMARY
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "src" ] && [ ! -d "htdocs" ]; then
|
||||||
|
echo "- Warning: No src/ or htdocs/ directory" >> $GITHUB_STEP_SUMMARY
|
||||||
|
else
|
||||||
|
echo "- Source directory present" >> $GITHUB_STEP_SUMMARY
|
||||||
|
fi
|
||||||
|
|
||||||
|
# -- Platform-specific checks --------
|
||||||
|
case "$PLATFORM" in
|
||||||
|
joomla)
|
||||||
|
if [ -n "$MANIFEST" ]; then
|
||||||
|
XML_VER=$(sed -n 's/.*<version>\([^<]*\)<\/version>.*/\1/p' "$MANIFEST" 2>/dev/null | head -1)
|
||||||
|
if [ -n "$XML_VER" ] && [ "$XML_VER" != "$VERSION" ]; then
|
||||||
|
echo "- Manifest drift: \`${XML_VER}\` != \`${VERSION}\`" >> $GITHUB_STEP_SUMMARY
|
||||||
|
ERRORS=$((ERRORS+1))
|
||||||
|
else
|
||||||
|
echo "- Manifest version: \`${VERSION}\`" >> $GITHUB_STEP_SUMMARY
|
||||||
|
fi
|
||||||
|
TYPE=$(sed -n 's/.*<extension[^>]*type="\([^"]*\)".*/\1/p' "$MANIFEST" 2>/dev/null)
|
||||||
|
echo "- Extension type: ${TYPE:-unknown}" >> $GITHUB_STEP_SUMMARY
|
||||||
|
else
|
||||||
|
echo "- No Joomla XML manifest (WaaS site)" >> $GITHUB_STEP_SUMMARY
|
||||||
|
fi ;;
|
||||||
|
dolibarr)
|
||||||
|
if [ -n "$MOD_FILE" ]; then
|
||||||
|
MOD_VER=$(sed -n "s/.*\\\$this->version = '\([^']*\)'.*/\1/p" "$MOD_FILE" 2>/dev/null | head -1)
|
||||||
|
if [ -n "$MOD_VER" ] && [ "$MOD_VER" != "$VERSION" ]; then
|
||||||
|
echo "- Module drift: \`${MOD_VER}\` != \`${VERSION}\`" >> $GITHUB_STEP_SUMMARY
|
||||||
|
ERRORS=$((ERRORS+1))
|
||||||
|
else
|
||||||
|
echo "- Module version: \`${VERSION}\`" >> $GITHUB_STEP_SUMMARY
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "- No mod*.class.php found" >> $GITHUB_STEP_SUMMARY
|
||||||
|
ERRORS=$((ERRORS+1))
|
||||||
|
fi
|
||||||
|
if [ ! -f "update.txt" ]; then
|
||||||
|
echo "- Missing update.txt" >> $GITHUB_STEP_SUMMARY
|
||||||
|
ERRORS=$((ERRORS+1))
|
||||||
|
fi ;;
|
||||||
|
*) echo "- Generic platform � no manifest checks" >> $GITHUB_STEP_SUMMARY ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
|
if [ "$ERRORS" -gt 0 ]; then
|
||||||
|
echo "**${ERRORS} error(s) — release may be incomplete**" >> $GITHUB_STEP_SUMMARY
|
||||||
|
else
|
||||||
|
echo "**All sanity checks passed**" >> $GITHUB_STEP_SUMMARY
|
||||||
|
fi
|
||||||
|
|
||||||
|
# -- STEP 2: Create or update version/XX.YY archive branch ---------------
|
||||||
|
# Always runs — every version change on main archives to version/XX.YY
|
||||||
|
- name: "Step 2: Version archive branch"
|
||||||
|
if: steps.check.outputs.already_released != 'true'
|
||||||
|
run: |
|
||||||
|
BRANCH="${{ steps.version.outputs.branch }}"
|
||||||
|
IS_MINOR="${{ steps.version.outputs.is_minor }}"
|
||||||
|
PATCH="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||||
|
PATCH_NUM=$(echo "$PATCH" | awk -F. '{print $3}')
|
||||||
|
|
||||||
|
# Check if branch exists
|
||||||
|
if git ls-remote --heads origin "$BRANCH" | grep -q "$BRANCH"; then
|
||||||
|
git push origin HEAD:"$BRANCH" --force
|
||||||
|
echo "Updated archive branch: ${BRANCH} (patch ${PATCH_NUM})" >> $GITHUB_STEP_SUMMARY
|
||||||
|
else
|
||||||
|
git checkout -b "$BRANCH" 2>/dev/null || git checkout "$BRANCH"
|
||||||
|
git push origin "$BRANCH" --force
|
||||||
|
echo "Created archive branch: ${BRANCH}" >> $GITHUB_STEP_SUMMARY
|
||||||
|
fi
|
||||||
|
|
||||||
|
# -- STEP 3: Set platform version ----------------------------------------
|
||||||
|
- name: "Step 3: Set platform version"
|
||||||
|
if: >-
|
||||||
|
steps.version.outputs.skip != 'true' &&
|
||||||
|
steps.check.outputs.already_released != 'true'
|
||||||
|
run: |
|
||||||
|
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||||
|
php /tmp/moko-platform-api/cli/version_set_platform.php \
|
||||||
|
--path . --version "$VERSION" --branch main
|
||||||
|
|
||||||
|
# -- STEP 4: Update version badges ----------------------------------------
|
||||||
|
- name: "Step 4: Update version badges"
|
||||||
|
if: >-
|
||||||
|
steps.version.outputs.skip != 'true' &&
|
||||||
|
steps.check.outputs.already_released != 'true'
|
||||||
|
run: |
|
||||||
|
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||||
|
php /tmp/moko-platform-api/cli/badge_update.php --path . --version "$VERSION"
|
||||||
|
|
||||||
|
# -- STEP 5: Write updates.xml (Joomla update server) ---------------------
|
||||||
|
- name: "Step 5: Write update stream"
|
||||||
|
id: updates
|
||||||
|
if: >-
|
||||||
|
steps.version.outputs.skip != 'true' &&
|
||||||
|
steps.check.outputs.already_released != 'true'
|
||||||
|
run: |
|
||||||
|
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||||
|
CLI="/tmp/moko-platform-api/cli"
|
||||||
|
|
||||||
|
# Generate updates.xml with all stability channels + suffixed versions
|
||||||
|
# Also exports ext_element, ext_name, ext_type, ext_folder to GITHUB_OUTPUT
|
||||||
|
php $CLI/updates_xml_build.php \
|
||||||
|
--path . \
|
||||||
|
--version "$VERSION" \
|
||||||
|
--stability stable \
|
||||||
|
--gitea-url "${GITEA_URL}" \
|
||||||
|
--org "${GITEA_ORG}" \
|
||||||
|
--repo "${GITEA_REPO}" \
|
||||||
|
--github-output
|
||||||
|
|
||||||
|
echo "updates.xml: ${VERSION} (all channels updated to stable)" >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
|
# -- Commit all changes ---------------------------------------------------
|
||||||
|
- name: Commit release changes
|
||||||
|
if: >-
|
||||||
|
steps.version.outputs.skip != 'true' &&
|
||||||
|
steps.check.outputs.already_released != 'true'
|
||||||
|
run: |
|
||||||
|
if git diff --quiet && git diff --cached --quiet; then
|
||||||
|
echo "No changes to commit"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||||
|
git 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="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>"
|
||||||
|
git push -u origin HEAD
|
||||||
|
|
||||||
|
# -- STEP 6: Create tag ---------------------------------------------------
|
||||||
|
- name: "Step 6: Create git tag"
|
||||||
|
if: >-
|
||||||
|
steps.version.outputs.skip != 'true' &&
|
||||||
|
steps.check.outputs.tag_exists != 'true' &&
|
||||||
|
steps.version.outputs.is_minor == 'true'
|
||||||
|
run: |
|
||||||
|
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
|
||||||
|
# Only create the major release tag if it doesn't exist yet
|
||||||
|
if ! git rev-parse "$RELEASE_TAG" >/dev/null 2>&1; then
|
||||||
|
git tag "$RELEASE_TAG"
|
||||||
|
git push origin "$RELEASE_TAG"
|
||||||
|
echo "Tag created: ${RELEASE_TAG}" >> $GITHUB_STEP_SUMMARY
|
||||||
|
else
|
||||||
|
echo "Tag ${RELEASE_TAG} already exists" >> $GITHUB_STEP_SUMMARY
|
||||||
|
fi
|
||||||
|
echo "Tag: ${TAG}" >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
|
# -- STEP 7: Create or update Gitea Release --------------------------------
|
||||||
|
- name: "Step 7: Gitea Release"
|
||||||
|
if: >-
|
||||||
|
steps.version.outputs.skip != 'true'
|
||||||
|
run: |
|
||||||
|
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||||
|
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
|
||||||
|
BRANCH="${{ steps.version.outputs.branch }}"
|
||||||
|
CLI="/tmp/moko-platform-api/cli"
|
||||||
|
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||||
|
|
||||||
|
# Reuse metadata from Step 5
|
||||||
|
EXT_NAME="${{ steps.updates.outputs.ext_name }}"
|
||||||
|
TYPE_PREFIX="${{ steps.updates.outputs.type_prefix }}"
|
||||||
|
EXT_ELEMENT="${{ steps.updates.outputs.ext_element }}"
|
||||||
|
[ -z "$EXT_NAME" ] && EXT_NAME="${GITEA_REPO}"
|
||||||
|
[ -z "$EXT_ELEMENT" ] && EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
|
||||||
|
|
||||||
|
RELEASE_NAME="${EXT_NAME} ${VERSION} (${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION})"
|
||||||
|
NOTES=$(php $CLI/release_notes.php --path . --version "$VERSION" 2>/dev/null)
|
||||||
|
[ -z "$NOTES" ] && NOTES="Release ${VERSION}"
|
||||||
|
|
||||||
|
php $CLI/release_manage.php \
|
||||||
|
--action create \
|
||||||
|
--tag "$RELEASE_TAG" \
|
||||||
|
--name "$RELEASE_NAME" \
|
||||||
|
--body "## ${VERSION} ($(date +%Y-%m-%d))\n${NOTES}" \
|
||||||
|
--target "$BRANCH" \
|
||||||
|
--token "${{ secrets.GA_TOKEN }}" \
|
||||||
|
--api-base "$API_BASE"
|
||||||
|
|
||||||
|
echo "Release created: ${RELEASE_NAME}" >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
|
# -- STEP 8: Build package, upload, and update checksums -------------------
|
||||||
|
- name: "Step 8: Build package and upload"
|
||||||
|
if: >-
|
||||||
|
steps.version.outputs.skip != 'true'
|
||||||
|
run: |
|
||||||
|
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||||
|
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
|
||||||
|
CLI="/tmp/moko-platform-api/cli"
|
||||||
|
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||||
|
|
||||||
|
# Build ZIP + tar.gz via CLI (handles single and multi-extension packages)
|
||||||
|
php $CLI/package_build.php --path . --version "$VERSION" --output-dir /tmp --github-output
|
||||||
|
|
||||||
|
# Read outputs from package_build
|
||||||
|
ZIP_NAME="${{ steps.updates.outputs.type_prefix }}${{ steps.updates.outputs.ext_element }}-${VERSION}.zip"
|
||||||
|
TAR_NAME="${{ steps.updates.outputs.type_prefix }}${{ steps.updates.outputs.ext_element }}-${VERSION}.tar.gz"
|
||||||
|
|
||||||
|
# Upload assets to release (handles dedup automatically)
|
||||||
|
php $CLI/release_manage.php \
|
||||||
|
--action upload \
|
||||||
|
--tag "$RELEASE_TAG" \
|
||||||
|
--files "/tmp/${ZIP_NAME},/tmp/${TAR_NAME}" \
|
||||||
|
--token "${{ secrets.GA_TOKEN }}" \
|
||||||
|
--api-base "$API_BASE"
|
||||||
|
|
||||||
|
# Regenerate updates.xml with SHA-256 from built package
|
||||||
|
SHA256_ZIP=$(sha256sum "/tmp/${ZIP_NAME}" | cut -d' ' -f1)
|
||||||
|
php $CLI/updates_xml_build.php \
|
||||||
|
--path . \
|
||||||
|
--version "$VERSION" \
|
||||||
|
--stability stable \
|
||||||
|
--sha "$SHA256_ZIP" \
|
||||||
|
--gitea-url "${GITEA_URL}" \
|
||||||
|
--org "${GITEA_ORG}" \
|
||||||
|
--repo "${GITEA_REPO}"
|
||||||
|
|
||||||
|
# Commit updated updates.xml
|
||||||
|
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 API (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"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build release body with changelog + SHA
|
||||||
|
NOTES=$(php $CLI/release_notes.php --path . --version "$VERSION" 2>/dev/null)
|
||||||
|
SHA256_TAR=""
|
||||||
|
[ -f "/tmp/${TAR_NAME}" ] && SHA256_TAR=$(sha256sum "/tmp/${TAR_NAME}" | cut -d' ' -f1)
|
||||||
|
|
||||||
|
BODY="## ${VERSION} ($(date +%Y-%m-%d))\n\n${NOTES}\n\n---\n\n### Checksums\n\n"
|
||||||
|
BODY="${BODY}| File | SHA-256 |\n|------|--------|\n"
|
||||||
|
BODY="${BODY}| \`${ZIP_NAME}\` | \`${SHA256_ZIP}\` |\n"
|
||||||
|
[ -n "$SHA256_TAR" ] && BODY="${BODY}| \`${TAR_NAME}\` | \`${SHA256_TAR}\` |\n"
|
||||||
|
|
||||||
|
printf '%b' "$BODY" > /tmp/release_body.md
|
||||||
|
php $CLI/release_manage.php \
|
||||||
|
--action update-body \
|
||||||
|
--tag "$RELEASE_TAG" \
|
||||||
|
--body-file /tmp/release_body.md \
|
||||||
|
--token "${{ secrets.GA_TOKEN }}" \
|
||||||
|
--api-base "$API_BASE"
|
||||||
|
|
||||||
|
echo "### Packages" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "| Package | SHA-256 |" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "|---------|---------|" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "| \`${ZIP_NAME}\` | \`${SHA256_ZIP}\` |" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "| \`${TAR_NAME}\` | \`${SHA256_TAR}\` |" >> $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.bump.outputs.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/moko-platform-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
|
||||||
|
|
||||||
|
# -- STEP 10: Sync main branch to GitHub mirror ----------------------------
|
||||||
|
- name: "Step 10: Push main to GitHub mirror"
|
||||||
|
if: >-
|
||||||
|
steps.version.outputs.skip != 'true' &&
|
||||||
|
secrets.GH_TOKEN != ''
|
||||||
|
continue-on-error: true
|
||||||
|
run: |
|
||||||
|
GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
|
||||||
|
GH_ORG=$(echo "$GH_REPO" | cut -d/ -f1)
|
||||||
|
GH_NAME=$(echo "$GH_REPO" | cut -d/ -f2)
|
||||||
|
git remote add github "https://x-access-token:${{ secrets.GH_TOKEN }}@github.com/${GH_ORG}/${GH_NAME}.git" 2>/dev/null || \
|
||||||
|
git remote set-url github "https://x-access-token:${{ secrets.GH_TOKEN }}@github.com/${GH_ORG}/${GH_NAME}.git"
|
||||||
|
git fetch origin main --depth=1
|
||||||
|
git push github origin/main:refs/heads/main --force 2>/dev/null \
|
||||||
|
&& echo "main branch pushed to GitHub mirror" \
|
||||||
|
|| echo "WARNING: GitHub mirror push failed"
|
||||||
|
|
||||||
|
# -- Clean up lesser pre-releases (cascade) ---------------------------------
|
||||||
|
- name: "Delete lesser pre-release channels"
|
||||||
|
if: steps.version.outputs.skip != 'true'
|
||||||
|
continue-on-error: true
|
||||||
|
run: |
|
||||||
|
php /tmp/moko-platform-api/cli/release_cascade.php \
|
||||||
|
--stability stable \
|
||||||
|
--token "${{ secrets.GA_TOKEN }}" \
|
||||||
|
--api-base "${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||||
|
|
||||||
|
# -- STEP 11: Reset dev branch from main ------------------------------------
|
||||||
|
- name: "Step 11: Delete and recreate dev branch from main"
|
||||||
|
if: steps.version.outputs.skip != 'true'
|
||||||
|
continue-on-error: true
|
||||||
|
run: |
|
||||||
|
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||||
|
TOKEN="${{ secrets.GA_TOKEN }}"
|
||||||
|
|
||||||
|
# Delete dev branch
|
||||||
|
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
|
||||||
|
"${API_BASE}/branches/dev" 2>/dev/null && echo "Deleted dev branch"
|
||||||
|
|
||||||
|
# Recreate dev from main (now includes version bump + changelog promotion)
|
||||||
|
curl -sf -X POST -H "Authorization: token ${TOKEN}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
"${API_BASE}/branches" \
|
||||||
|
-d '{"new_branch_name":"dev","old_branch_name":"main"}' 2>/dev/null && echo "Recreated dev from main"
|
||||||
|
|
||||||
|
echo "Dev branch reset from main (keeps dev ahead after release)" >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
|
|
||||||
|
# -- Dolibarr post-release: Reset dev version -----------------------------
|
||||||
|
- name: "Dolibarr: Reset dev version"
|
||||||
|
if: >-
|
||||||
|
steps.version.outputs.skip != 'true' &&
|
||||||
|
steps.platform.outputs.platform == 'dolibarr' &&
|
||||||
|
steps.platform.outputs.mod_file != ''
|
||||||
|
continue-on-error: true
|
||||||
|
run: |
|
||||||
|
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||||
|
TOKEN="${{ secrets.GA_TOKEN }}"
|
||||||
|
MOD_FILE="${{ steps.platform.outputs.mod_file }}"
|
||||||
|
ENCODED_PATH=$(echo "$MOD_FILE" | sed 's|^\./||' | python3 -c "import sys,urllib.parse; print(urllib.parse.quote(sys.stdin.read().strip()))")
|
||||||
|
FILE_RESP=$(curl -sf -H "Authorization: token ${TOKEN}" "${API_BASE}/contents/${ENCODED_PATH}?ref=dev" 2>/dev/null || true)
|
||||||
|
FILE_SHA=$(echo "$FILE_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin).get('sha',''))" 2>/dev/null || true)
|
||||||
|
FILE_CONTENT=$(echo "$FILE_RESP" | python3 -c "import sys,json,base64; print(base64.b64decode(json.load(sys.stdin).get('content','')).decode())" 2>/dev/null || true)
|
||||||
|
if [ -n "$FILE_SHA" ] && [ -n "$FILE_CONTENT" ]; then
|
||||||
|
UPDATED=$(echo "$FILE_CONTENT" | sed "s/\$this->version = '[^']*'/\$this->version = 'development'/")
|
||||||
|
ENCODED=$(echo "$UPDATED" | base64 -w0)
|
||||||
|
curl -sf -X PUT -H "Authorization: token ${TOKEN}" -H "Content-Type: application/json" "${API_BASE}/contents/${ENCODED_PATH}" \
|
||||||
|
-d "$(jq -n --arg content \"$ENCODED\" --arg sha \"$FILE_SHA\" --arg msg \"chore(version): reset dev version [skip ci]\" --arg branch \"dev\" '{content:$content,sha:$sha,message:$msg,branch:$branch}')" > /dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# -- Summary --------------------------------------------------------------
|
||||||
|
- name: Pipeline Summary
|
||||||
|
if: always()
|
||||||
|
run: |
|
||||||
|
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||||
|
PLATFORM="${{ steps.platform.outputs.platform }}"
|
||||||
|
if [ "${{ steps.version.outputs.skip }}" = "true" ]; then
|
||||||
|
echo "## Release Skipped" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "No VERSION in README.md" >> $GITHUB_STEP_SUMMARY
|
||||||
|
elif [ "${{ steps.check.outputs.already_released }}" = "true" ]; then
|
||||||
|
echo "## Already Released — ${VERSION}" >> $GITHUB_STEP_SUMMARY
|
||||||
|
else
|
||||||
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "## Build & Release Complete (${PLATFORM})" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "| Step | Result |" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "|------|--------|" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "| Platform | \`${PLATFORM}\` |" >> $GITHUB_STEP_SUMMARY
|
||||||
|
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](${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/${{ steps.version.outputs.tag }}) |" >> $GITHUB_STEP_SUMMARY
|
||||||
|
fi
|
||||||
@@ -87,13 +87,13 @@ jobs:
|
|||||||
done
|
done
|
||||||
|
|
||||||
# ── Version ──────────────────────────────────────────────────────
|
# ── Version ──────────────────────────────────────────────────────
|
||||||
- name: Setup MokoStandards tools
|
- name: Setup moko-platform tools
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
|
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
|
||||||
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
|
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
|
||||||
run: |
|
run: |
|
||||||
git clone --depth 1 --branch version/04 --quiet \
|
git clone --depth 1 --branch version/04 --quiet \
|
||||||
"https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \
|
"https://x-access-token:${GH_TOKEN}@github.com/MokoConsulting/moko-platform.git" \
|
||||||
/tmp/mokostandards
|
/tmp/mokostandards
|
||||||
cd /tmp/mokostandards
|
cd /tmp/mokostandards
|
||||||
composer install --no-dev --no-interaction --quiet
|
composer install --no-dev --no-interaction --quiet
|
||||||
@@ -0,0 +1,225 @@
|
|||||||
|
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
#
|
||||||
|
# FILE INFORMATION
|
||||||
|
# DEFGROUP: Gitea.Workflow
|
||||||
|
# INGROUP: moko-platform.Release
|
||||||
|
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
|
||||||
|
# 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
|
||||||
|
|
||||||
|
name: "Universal: Pre-Release"
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
stability:
|
||||||
|
description: 'Pre-release channel'
|
||||||
|
required: true
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- development
|
||||||
|
- alpha
|
||||||
|
- beta
|
||||||
|
- release-candidate
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
env:
|
||||||
|
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 }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: "Build Pre-Release (${{ inputs.stability }})"
|
||||||
|
runs-on: release
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
token: ${{ secrets.GA_TOKEN }}
|
||||||
|
|
||||||
|
- name: Setup moko-platform tools
|
||||||
|
env:
|
||||||
|
MOKO_CLONE_TOKEN: ${{ secrets.GA_TOKEN }}
|
||||||
|
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
||||||
|
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN }}"}}'
|
||||||
|
run: |
|
||||||
|
if ! command -v composer &> /dev/null; 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
|
||||||
|
git clone --depth 1 --branch main --quiet \
|
||||||
|
"https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git" \
|
||||||
|
/tmp/moko-platform-api
|
||||||
|
cd /tmp/moko-platform-api
|
||||||
|
composer install --no-dev --no-interaction --quiet
|
||||||
|
|
||||||
|
- name: Detect platform
|
||||||
|
id: platform
|
||||||
|
run: |
|
||||||
|
PLATFORM=$(sed -n 's/.*<platform>\([^<]*\)<\/platform>.*/\1/p' .mokogitea/manifest.xml 2>/dev/null | head -1 | tr -d '[:space:]')
|
||||||
|
[ -z "$PLATFORM" ] && PLATFORM=$(sed -n 's/.*<platform>\([^<]*\)<\/platform>.*/\1/p' .gitea/manifest.xml 2>/dev/null | head -1 | tr -d '[:space:]')
|
||||||
|
[ -z "$PLATFORM" ] && PLATFORM="generic"
|
||||||
|
echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Resolve metadata and bump version
|
||||||
|
id: meta
|
||||||
|
run: |
|
||||||
|
CLI="/tmp/moko-platform-api/cli"
|
||||||
|
STABILITY="${{ inputs.stability }}"
|
||||||
|
|
||||||
|
case "$STABILITY" in
|
||||||
|
development) SUFFIX="-dev"; TAG="development" ;;
|
||||||
|
alpha) SUFFIX="-alpha"; TAG="alpha" ;;
|
||||||
|
beta) SUFFIX="-beta"; TAG="beta" ;;
|
||||||
|
release-candidate) SUFFIX="-rc"; TAG="release-candidate" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Bump patch version via CLI
|
||||||
|
CURRENT=$(php $CLI/version_read.php --path . 2>/dev/null)
|
||||||
|
[ -z "$CURRENT" ] && CURRENT="00.00.00"
|
||||||
|
php $CLI/version_bump.php --path .
|
||||||
|
VERSION=$(php $CLI/version_read.php --path . 2>/dev/null)
|
||||||
|
echo "Bumping: ${CURRENT} → ${VERSION} (patch)"
|
||||||
|
|
||||||
|
# Set platform-specific version with stability suffix
|
||||||
|
php $CLI/version_set_platform.php \
|
||||||
|
--path . --version "$VERSION" --stability "$STABILITY" --branch "${{ github.ref_name }}"
|
||||||
|
|
||||||
|
# Commit version bump
|
||||||
|
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
||||||
|
git config --local user.name "gitea-actions[bot]"
|
||||||
|
git remote set-url origin "https://jmiller:${{ secrets.GA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
||||||
|
git add -A
|
||||||
|
git diff --cached --quiet || {
|
||||||
|
git commit -m "chore(version): bump ${CURRENT} → ${VERSION}${SUFFIX} [skip ci]"
|
||||||
|
git push origin HEAD 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "stability=${STABILITY}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "suffix=${SUFFIX}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Build package
|
||||||
|
id: package
|
||||||
|
run: |
|
||||||
|
CLI="/tmp/moko-platform-api/cli"
|
||||||
|
VERSION="${{ steps.meta.outputs.version }}"
|
||||||
|
SUFFIX="${{ steps.meta.outputs.suffix }}"
|
||||||
|
|
||||||
|
# Build ZIP + tar.gz via CLI (handles type prefix, excludes, multi-extension packages)
|
||||||
|
php $CLI/package_build.php \
|
||||||
|
--path . \
|
||||||
|
--version "${VERSION}${SUFFIX}" \
|
||||||
|
--output-dir build \
|
||||||
|
--github-output
|
||||||
|
|
||||||
|
- name: Create release and upload
|
||||||
|
run: |
|
||||||
|
CLI="/tmp/moko-platform-api/cli"
|
||||||
|
VERSION="${{ steps.meta.outputs.version }}"
|
||||||
|
SUFFIX="${{ steps.meta.outputs.suffix }}"
|
||||||
|
TAG="${{ steps.meta.outputs.tag }}"
|
||||||
|
STABILITY="${{ steps.meta.outputs.stability }}"
|
||||||
|
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||||
|
EXT_ELEMENT="${{ steps.package.outputs.ext_element }}"
|
||||||
|
[ -z "$EXT_ELEMENT" ] && EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
|
||||||
|
|
||||||
|
SHA256="${{ steps.package.outputs.sha256_zip }}"
|
||||||
|
ZIP_PATH="${{ steps.package.outputs.zip_path }}"
|
||||||
|
TAR_PATH="${{ steps.package.outputs.tar_path }}"
|
||||||
|
|
||||||
|
# Create release
|
||||||
|
php $CLI/release_manage.php \
|
||||||
|
--action create \
|
||||||
|
--tag "$TAG" \
|
||||||
|
--name "${EXT_ELEMENT} ${VERSION}${SUFFIX} (${STABILITY})" \
|
||||||
|
--body "## ${VERSION}${SUFFIX} ($(date +%Y-%m-%d))\n**Channel:** ${STABILITY}\n**SHA-256:** \`${SHA256}\`" \
|
||||||
|
--target "${{ github.ref_name }}" \
|
||||||
|
--token "${{ secrets.GA_TOKEN }}" \
|
||||||
|
--api-base "$API_BASE"
|
||||||
|
|
||||||
|
# Upload assets
|
||||||
|
FILES="${ZIP_PATH}"
|
||||||
|
[ -f "$TAR_PATH" ] && FILES="${FILES},${TAR_PATH}"
|
||||||
|
php $CLI/release_manage.php \
|
||||||
|
--action upload \
|
||||||
|
--tag "$TAG" \
|
||||||
|
--files "$FILES" \
|
||||||
|
--token "${{ secrets.GA_TOKEN }}" \
|
||||||
|
--api-base "$API_BASE"
|
||||||
|
|
||||||
|
- name: Update updates.xml
|
||||||
|
if: steps.platform.outputs.platform == 'joomla'
|
||||||
|
run: |
|
||||||
|
CLI="/tmp/moko-platform-api/cli"
|
||||||
|
VERSION="${{ steps.meta.outputs.version }}"
|
||||||
|
STABILITY="${{ steps.meta.outputs.stability }}"
|
||||||
|
SHA256="${{ steps.package.outputs.sha256_zip }}"
|
||||||
|
|
||||||
|
# Map stability names
|
||||||
|
case "$STABILITY" in
|
||||||
|
release-candidate) CLI_STABILITY="rc" ;;
|
||||||
|
*) CLI_STABILITY="$STABILITY" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Generate updates.xml with stability-suffixed versions
|
||||||
|
php $CLI/updates_xml_build.php \
|
||||||
|
--path . \
|
||||||
|
--version "$VERSION" \
|
||||||
|
--stability "$CLI_STABILITY" \
|
||||||
|
--sha "$SHA256" \
|
||||||
|
--gitea-url "${GITEA_URL}" \
|
||||||
|
--org "${GITEA_ORG}" \
|
||||||
|
--repo "${GITEA_REPO}"
|
||||||
|
|
||||||
|
# Commit and push
|
||||||
|
if ! git diff --quiet updates.xml 2>/dev/null; then
|
||||||
|
git add updates.xml
|
||||||
|
git commit -m "chore: update ${STABILITY} channel ${VERSION} [skip ci]"
|
||||||
|
git push origin HEAD 2>&1 || echo "WARNING: push failed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: "Sync updates.xml to all branches"
|
||||||
|
if: steps.platform.outputs.platform == 'joomla'
|
||||||
|
run: |
|
||||||
|
CURRENT_BRANCH="${{ github.ref_name }}"
|
||||||
|
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
||||||
|
git config --local user.name "gitea-actions[bot]"
|
||||||
|
|
||||||
|
for BRANCH in main dev; do
|
||||||
|
[ "$BRANCH" = "$CURRENT_BRANCH" ] && continue
|
||||||
|
echo "Syncing updates.xml → ${BRANCH}"
|
||||||
|
git fetch origin "${BRANCH}" 2>/dev/null || continue
|
||||||
|
git checkout "origin/${BRANCH}" -- . 2>/dev/null || continue
|
||||||
|
git checkout "${CURRENT_BRANCH}" -- updates.xml
|
||||||
|
if ! git diff --quiet updates.xml 2>/dev/null; then
|
||||||
|
git add updates.xml
|
||||||
|
git commit -m "chore: sync updates.xml from ${CURRENT_BRANCH} [skip ci]"
|
||||||
|
git push origin HEAD:refs/heads/${BRANCH} 2>&1 || echo "WARNING: push to ${BRANCH} failed"
|
||||||
|
fi
|
||||||
|
git checkout "${CURRENT_BRANCH}" 2>/dev/null
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: "Delete lesser pre-release channels (cascade)"
|
||||||
|
continue-on-error: true
|
||||||
|
run: |
|
||||||
|
STABILITY="${{ steps.meta.outputs.stability }}"
|
||||||
|
|
||||||
|
# Map workflow stability names to CLI names
|
||||||
|
case "$STABILITY" in
|
||||||
|
release-candidate) CLI_STABILITY="rc" ;;
|
||||||
|
*) CLI_STABILITY="$STABILITY" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
php /tmp/moko-platform-api/cli/release_cascade.php \
|
||||||
|
--stability "$CLI_STABILITY" \
|
||||||
|
--token "${{ secrets.GA_TOKEN }}" \
|
||||||
|
--api-base "${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||||
@@ -42,6 +42,8 @@ This is an MCP (Model Context Protocol) server. Key files:
|
|||||||
|
|
||||||
## Rules
|
## Rules
|
||||||
|
|
||||||
|
- **Workflow directory**: `.mokogitea/` (not `.gitea/` or `.github/`)
|
||||||
|
|
||||||
- **Never commit** `.claude/`, `.mcp.json`, `TODO.md`, or `*.min.css`/`*.min.js`
|
- **Never commit** `.claude/`, `.mcp.json`, `TODO.md`, or `*.min.css`/`*.min.js`
|
||||||
- **Attribution**: use `Authored-by: Moko Consulting` in commits
|
- **Attribution**: use `Authored-by: Moko Consulting` in commits
|
||||||
- **Branch strategy**: develop on `dev`, merge to `main` for release
|
- **Branch strategy**: develop on `dev`, merge to `main` for release
|
||||||
|
|||||||
Reference in New Issue
Block a user