diff --git a/.mokogitea/workflows/pre-release.yml b/.mokogitea/workflows/pre-release.yml index 234a949..44d3de6 100644 --- a/.mokogitea/workflows/pre-release.yml +++ b/.mokogitea/workflows/pre-release.yml @@ -8,7 +8,7 @@ # 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 +# BRIEF: Manual pre-release -- builds dev/alpha/beta/rc packages from any branch name: "Universal: Pre-Release" @@ -45,33 +45,45 @@ jobs: 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 }}"}}' + - name: Setup tools 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 + # Update moko-platform CLI tools if available; install PHP if missing + if command -v moko-platform-update &> /dev/null; then + moko-platform-update + elif [ -d "/opt/moko-platform" ]; then + cd /opt/moko-platform && git pull origin main --quiet 2>/dev/null || true + else + if ! command -v php &> /dev/null; then + sudo apt-get update -qq + sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl >/dev/null 2>&1 + fi + git clone --depth 1 --branch main --quiet \ + "https://x-access-token:${{ secrets.GA_TOKEN }}@git.mokoconsulting.tech/MokoConsulting/moko-platform.git" \ + /tmp/moko-platform-api + fi + # Set MOKO_CLI to whichever path exists + if [ -d "/opt/moko-platform/cli" ]; then + echo "MOKO_CLI=/opt/moko-platform/cli" >> "$GITHUB_ENV" + else + echo "MOKO_CLI=/tmp/moko-platform-api/cli" >> "$GITHUB_ENV" fi - 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>.*/\1/p' .mokogitea/manifest.xml 2>/dev/null | head -1 | tr -d '[:space:]') - [ -z "$PLATFORM" ] && PLATFORM=$(sed -n 's/.*\([^<]*\)<\/platform>.*/\1/p' .gitea/manifest.xml 2>/dev/null | head -1 | tr -d '[:space:]') [ -z "$PLATFORM" ] && PLATFORM="generic" echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT" + MANIFEST=$(find ./src -maxdepth 1 -name "pkg_*.xml" -exec grep -l '/dev/null | head -1) + [ -z "$MANIFEST" ] && MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" ! -path "*/packages/*" -exec grep -l '/dev/null | head -1) + [ -z "$MANIFEST" ] && MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '/dev/null | head -1) + MOD_FILE=$(find . -maxdepth 4 -name "mod*.class.php" ! -path "./.git/*" -exec grep -l 'extends DolibarrModules' {} \; 2>/dev/null | head -1) + echo "manifest=${MANIFEST}" >> "$GITHUB_OUTPUT" + echo "mod_file=${MOD_FILE}" >> "$GITHUB_OUTPUT" - name: Resolve metadata and bump version id: meta run: | - CLI="/tmp/moko-platform-api/cli" STABILITY="${{ inputs.stability }}" case "$STABILITY" in @@ -81,16 +93,19 @@ jobs: 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)" + # Patch bump via CLI tool + php ${MOKO_CLI}/version_bump.php --path . + VERSION=$(php ${MOKO_CLI}/version_read.php --path . 2>/dev/null) + [ -z "$VERSION" ] && VERSION="00.00.01" + TODAY=$(date +%Y-%m-%d) - # Set platform-specific version with stability suffix - php $CLI/version_set_platform.php \ - --path . --version "$VERSION" --stability "$STABILITY" --branch "${{ github.ref_name }}" + # Update platform-specific manifest + PLATFORM="${{ steps.platform.outputs.platform }}" + MANIFEST="${{ steps.platform.outputs.manifest }}" + MOD_FILE="${{ steps.platform.outputs.mod_file }}" + + php ${MOKO_CLI}/version_set_platform.php \ + --path . --version "$VERSION" --branch "${{ github.ref_name }}" 2>/dev/null || true # Commit version bump git config --local user.email "gitea-actions[bot]@mokoconsulting.tech" @@ -98,90 +113,214 @@ jobs: 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 commit -m "chore(version): pre-release bump to ${VERSION} [skip ci]" git push origin HEAD 2>&1 } + # Auto-detect element (platform-aware) + EXT_ELEMENT="" + case "$PLATFORM" in + joomla) + if [ -n "$MANIFEST" ]; then + EXT_ELEMENT=$(sed -n 's/.*\([^<]*\)<\/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) + 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 - id: package run: | - CLI="/tmp/moko-platform-api/cli" - VERSION="${{ steps.meta.outputs.version }}" - SUFFIX="${{ steps.meta.outputs.suffix }}" + SOURCE_DIR="src" + [ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs" + if [ ! -d "$SOURCE_DIR" ]; then + echo "::error::No src/ or htdocs/ directory" + exit 1 + fi - # 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 + MANIFEST="${{ steps.meta.outputs.manifest }}" + EXT_TYPE="" + if [ -n "$MANIFEST" ]; then + EXT_TYPE=$(sed -n 's/.*]*type="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1) + fi - - name: Create release and upload + EXCLUDES="sftp-config* .ftpignore *.ppk *.pem *.key .env* *.local .build-trigger" + + mkdir -p build/package + + if [ "$EXT_TYPE" = "package" ] && [ -d "${SOURCE_DIR}/packages" ]; then + echo "=== Building Joomla PACKAGE (multi-extension) ===" + for ext_dir in "${SOURCE_DIR}"/packages/*/; do + [ ! -d "$ext_dir" ] && continue + EXT_NAME=$(basename "$ext_dir") + echo " Packaging sub-extension: ${EXT_NAME}" + cd "$ext_dir" + zip -r "../../build/package/${EXT_NAME}.zip" . -x $EXCLUDES + cd "$OLDPWD" + done + for f in "${SOURCE_DIR}"/*.xml "${SOURCE_DIR}"/*.php; do + [ -f "$f" ] && cp "$f" build/package/ + done + else + echo "=== Building standard extension ===" + rsync -a \ + --exclude='sftp-config*' \ + --exclude='.ftpignore' \ + --exclude='*.ppk' \ + --exclude='*.pem' \ + --exclude='*.key' \ + --exclude='.env*' \ + --exclude='*.local' \ + --exclude='.build-trigger' \ + "${SOURCE_DIR}/" build/package/ + fi + + - name: Create ZIP + id: zip + 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: | - CLI="/tmp/moko-platform-api/cli" - VERSION="${{ steps.meta.outputs.version }}" - SUFFIX="${{ steps.meta.outputs.suffix }}" TAG="${{ steps.meta.outputs.tag }}" + VERSION="${{ steps.meta.outputs.version }}" 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.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) - SHA256="${{ steps.package.outputs.sha256_zip }}" - ZIP_PATH="${{ steps.package.outputs.zip_path }}" - TAR_PATH="${{ steps.package.outputs.tar_path }}" + 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 - 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" + 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') - # 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" + 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: | - CLI="/tmp/moko-platform-api/cli" - VERSION="${{ steps.meta.outputs.version }}" STABILITY="${{ steps.meta.outputs.stability }}" - SHA256="${{ steps.package.outputs.sha256_zip }}" + VERSION="${{ steps.meta.outputs.version }}" + SHA256="${{ steps.zip.outputs.sha256 }}" + ZIP_NAME="${{ steps.meta.outputs.zip_name }}" + TAG="${{ steps.meta.outputs.tag }}" - # Map stability names + if [ ! -f "updates.xml" ]; then + echo "No updates.xml -- skipping" + exit 0 + fi + + # Map stability to XML tag name case "$STABILITY" in - release-candidate) CLI_STABILITY="rc" ;; - *) CLI_STABILITY="$STABILITY" ;; + development) XML_TAG="development" ;; + alpha) XML_TAG="alpha" ;; + beta) XML_TAG="beta" ;; + release-candidate) XML_TAG="rc" ;; + *) XML_TAG="$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}" + DOWNLOAD_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/${TAG}/${ZIP_NAME}" + + # Use PHP to update the channel in updates.xml + php -r ' + $xml_tag = $argv[1]; + $version = $argv[2]; + $sha256 = $argv[3]; + $url = $argv[4]; + $date = date("Y-m-d"); + + $content = file_get_contents("updates.xml"); + $pattern = "/((?:(?!<\/update>).)*?" . 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}", $block); + if (strpos($block, "") !== false) { + $block = preg_replace("/[^<]*<\/sha256>/", "{$sha256}", $block); + } else { + $block = str_replace("", "\n {$sha256}", $block); + } + $block = preg_replace("/(]*>)[^<]*(<\/downloadurl>)/", "\${1}{$url}\${2}", $block); + return $block; + }, $content); + + file_put_contents("updates.xml", $content); + echo "Updated {$xml_tag} channel: version={$version}\n"; + ' "$XML_TAG" "$VERSION" "$SHA256" "$DOWNLOAD_URL" # Commit and push if ! git diff --quiet updates.xml 2>/dev/null; then + 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" @@ -196,7 +335,7 @@ jobs: for BRANCH in main dev; do [ "$BRANCH" = "$CURRENT_BRANCH" ] && continue - echo "Syncing updates.xml → ${BRANCH}" + 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 @@ -211,15 +350,26 @@ jobs: - 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 }}" + + php ${MOKO_CLI}/release_cascade.php \ + --stability "${{ steps.meta.outputs.stability }}" \ + --token "${TOKEN}" \ + --api-base "${API_BASE}" + + - name: Summary + if: always() + run: | + VERSION="${{ steps.meta.outputs.version }}" STABILITY="${{ steps.meta.outputs.stability }}" - - # 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}" + ZIP_NAME="${{ steps.meta.outputs.zip_name }}" + SHA256="${{ steps.zip.outputs.sha256 }}" + echo "## Pre-Release Complete" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY + echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY + echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY + echo "| Channel | ${STABILITY} |" >> $GITHUB_STEP_SUMMARY + echo "| Package | \`${ZIP_NAME}\` |" >> $GITHUB_STEP_SUMMARY + echo "| SHA-256 | \`${SHA256:-n/a}\` |" >> $GITHUB_STEP_SUMMARY