feat: release pipeline rework #211
@@ -16,10 +16,8 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
- alpha
|
||||
- beta
|
||||
- rc
|
||||
- 'feature/**'
|
||||
- 'patch/**'
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
@@ -82,71 +82,33 @@ jobs:
|
||||
cd /tmp/moko-platform-api
|
||||
composer install --no-dev --no-interaction --quiet
|
||||
|
||||
- name: Rename source branch to rc
|
||||
- name: Rename branch to rc
|
||||
run: |
|
||||
SOURCE_BRANCH="${{ github.event.pull_request.head.ref || 'dev' }}"
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
PR_NUM="${{ github.event.pull_request.number }}"
|
||||
php /tmp/moko-platform-api/cli/branch_rename.php \
|
||||
--from "$SOURCE_BRANCH" --to rc \
|
||||
--from "${{ github.event.pull_request.head.ref || 'dev' }}" --to rc \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
|
||||
--api-base "${API_BASE}" \
|
||||
--pr "$PR_NUM"
|
||||
--api-base "${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" \
|
||||
--pr "${{ github.event.pull_request.number }}"
|
||||
|
||||
- name: Set RC version on renamed branch
|
||||
- name: Checkout rc and configure git
|
||||
run: |
|
||||
# Checkout the new rc branch
|
||||
git fetch origin rc
|
||||
git checkout rc
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
MOKO_CLI="/tmp/moko-platform-api/cli"
|
||||
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
||||
git config --local user.name "gitea-actions[bot]"
|
||||
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
||||
|
||||
VERSION=$(php ${MOKO_CLI}/version_read.php --path .) || true
|
||||
[ -z "$VERSION" ] && { echo "No version — skipping"; exit 0; }
|
||||
|
||||
php ${MOKO_CLI}/version_set_platform.php \
|
||||
--path . --version "$VERSION" --branch rc --stability rc 2>/dev/null || true
|
||||
php ${MOKO_CLI}/version_check.php --path . --fix 2>/dev/null || true
|
||||
|
||||
if ! git diff --quiet || ! git diff --cached --quiet; then
|
||||
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
||||
git config --local user.name "gitea-actions[bot]"
|
||||
git add -A
|
||||
git commit -m "chore(version): set RC stability suffix [skip ci]" \
|
||||
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>"
|
||||
git push origin rc
|
||||
fi
|
||||
|
||||
- name: Build RC release
|
||||
- name: Publish RC release
|
||||
run: |
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
MOKO_CLI="/tmp/moko-platform-api/cli"
|
||||
VERSION=$(php ${MOKO_CLI}/version_read.php --path .) || true
|
||||
|
||||
php ${MOKO_CLI}/release_create.php \
|
||||
--path . --version "$VERSION" --tag "release-candidate" \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
|
||||
--repo "${GITEA_REPO}" --branch rc 2>&1 || true
|
||||
|
||||
php ${MOKO_CLI}/release_package.php \
|
||||
--path . --version "$VERSION" --tag "release-candidate" \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
|
||||
--repo "${GITEA_REPO}" --output /tmp 2>&1 || true
|
||||
|
||||
- name: Cascade lesser channels
|
||||
continue-on-error: true
|
||||
run: |
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
php /tmp/moko-platform-api/cli/release_cascade.php \
|
||||
--stability release-candidate \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
|
||||
--api-base "${API_BASE}"
|
||||
php /tmp/moko-platform-api/cli/release_publish.php \
|
||||
--path . --stability rc --bump minor --branch rc \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
|
||||
- name: Summary
|
||||
if: always()
|
||||
run: |
|
||||
echo "## Promoted to Release Candidate" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Draft PR opened — branch renamed to rc, RC release built" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Branch renamed to rc, minor bump, RC + lesser stream releases built, updates.xml synced" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# ── Merged PR → Build & Release (or promote RC to stable) ────────────────────
|
||||
release:
|
||||
@@ -390,64 +352,14 @@ jobs:
|
||||
echo "Release created: ${VERSION}" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# -- STEP 8: Build packages and upload to release ----------------------------
|
||||
- name: "Step 8: Build package and upload"
|
||||
id: package
|
||||
- name: "Publish stable release (+ copies for all lesser streams)"
|
||||
if: >-
|
||||
steps.version.outputs.skip != 'true' &&
|
||||
steps.rc.outputs.promote != 'true'
|
||||
run: |
|
||||
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
php /tmp/moko-platform-api/cli/release_package.php \
|
||||
--path . --version "$VERSION" --tag "$RELEASE_TAG" \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
|
||||
--repo "${GITEA_REPO}" --output /tmp || true
|
||||
|
||||
# -- STEP 5: Write update stream (after build so SHA-256 is available) -----
|
||||
- name: "Step 5: Write update stream"
|
||||
if: steps.version.outputs.skip != 'true'
|
||||
run: |
|
||||
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||
SHA256="${{ steps.package.outputs.sha256_zip }}"
|
||||
|
||||
# Fetch latest updates.xml from main so preserve logic has current channels
|
||||
GITEA_TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
|
||||
curl -sf -H "Authorization: token ${GITEA_TOKEN}" \
|
||||
"${API}/contents/updates.xml?ref=main" 2>/dev/null | \
|
||||
php -r "\$d=json_decode(file_get_contents('php://stdin'),true); echo base64_decode(\$d['content'] ?? '');" \
|
||||
> updates.xml 2>/dev/null || rm -f updates.xml
|
||||
|
||||
SHA_FLAG=""
|
||||
[ -n "$SHA256" ] && SHA_FLAG="--sha ${SHA256}"
|
||||
|
||||
php /tmp/moko-platform-api/cli/updates_xml_build.php \
|
||||
--path . --version "${VERSION}" --stability stable \
|
||||
--gitea-url "${GITEA_URL}" --org "${GITEA_ORG}" --repo "${GITEA_REPO}" \
|
||||
${SHA_FLAG} --github-output
|
||||
|
||||
# Commit updates.xml if changed
|
||||
if ! git diff --quiet updates.xml 2>/dev/null; then
|
||||
git add updates.xml
|
||||
git commit -m "chore: update stable channel ${VERSION} [skip ci]" \
|
||||
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>"
|
||||
git push origin HEAD:refs/heads/main 2>&1 || true
|
||||
fi
|
||||
|
||||
# -- STEP 8b: Update release description with changelog ----------------------
|
||||
- name: "Step 8b: Update release body"
|
||||
if: steps.version.outputs.skip != 'true'
|
||||
continue-on-error: true
|
||||
run: |
|
||||
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
|
||||
php /tmp/moko-platform-api/cli/release_body_update.php \
|
||||
--path . --version "${VERSION}" --tag "${RELEASE_TAG}" \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
|
||||
--gitea-url "${GITEA_URL}" --org "${GITEA_ORG}" --repo "${GITEA_REPO}" \
|
||||
2>&1 || true
|
||||
echo "Release body updated" >> $GITHUB_STEP_SUMMARY
|
||||
php /tmp/moko-platform-api/cli/release_publish.php \
|
||||
--path . --stability stable --branch main \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
|
||||
# -- STEP 9: Mirror to GitHub (stable only) --------------------------------
|
||||
- name: "Step 9: Mirror release to GitHub"
|
||||
@@ -484,33 +396,17 @@ jobs:
|
||||
&& echo "main branch pushed to GitHub mirror" \
|
||||
|| echo "WARNING: GitHub mirror push failed"
|
||||
|
||||
# -- Clean up lesser pre-releases (cascade) ---------------------------------
|
||||
# stable → deletes all | rc → beta,alpha,dev | beta → alpha,dev | alpha → dev
|
||||
- name: "Delete lesser pre-release channels"
|
||||
continue-on-error: true
|
||||
run: |
|
||||
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
php /tmp/moko-platform-api/cli/release_cascade.php \
|
||||
--stability stable \
|
||||
--version "${VERSION}" \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
|
||||
--api-base "${API_BASE}" 2>/dev/null || true
|
||||
|
||||
- name: "Step 11: Clean up pre-release branches and recreate dev from main"
|
||||
- name: "Step 11: Delete rc branch and recreate dev 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.MOKOGITEA_TOKEN }}"
|
||||
|
||||
# Delete ephemeral pre-release branches (rc, alpha, beta)
|
||||
for EPHEMERAL in rc alpha beta; do
|
||||
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
|
||||
"${API_BASE}/branches/${EPHEMERAL}" 2>/dev/null \
|
||||
&& echo "Deleted ${EPHEMERAL} branch" \
|
||||
|| echo "${EPHEMERAL} branch not found"
|
||||
done
|
||||
# Delete rc branch (ephemeral — created by promote-rc)
|
||||
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
|
||||
"${API_BASE}/branches/rc" 2>/dev/null \
|
||||
&& echo "Deleted rc branch" || echo "rc branch not found"
|
||||
|
||||
# Delete dev branch
|
||||
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
|
||||
|
||||
+2
-2
@@ -12,6 +12,8 @@ BRIEF: Release changelog
|
||||
# Changelog
|
||||
## [Unreleased]
|
||||
|
||||
## [09.09.00] --- 2026-05-30
|
||||
|
||||
## [09.09.00] --- 2026-05-29
|
||||
|
||||
## [09.08.00] --- 2026-05-29
|
||||
@@ -19,5 +21,3 @@ BRIEF: Release changelog
|
||||
## [09.07.00] --- 2026-05-29
|
||||
|
||||
## [09.06.00] --- 2026-05-29
|
||||
|
||||
## [09.05.00] --- 2026-05-29
|
||||
|
||||
+22
-2
@@ -88,13 +88,33 @@ Each branch appends a suffix to indicate stability:
|
||||
|
||||
### Auto version bump
|
||||
|
||||
On every push to `dev`, `alpha`, `beta`, `rc`, or `feature/*`:
|
||||
On every push to `dev`, `feature/*`, or `patch/*`:
|
||||
|
||||
1. Patch version incremented
|
||||
2. Stability suffix applied based on branch name
|
||||
2. Stability suffix `-dev` applied
|
||||
3. All version-bearing files updated (manifests, CHANGELOG, PHP headers, etc.)
|
||||
4. Commit created with `[skip ci]` to avoid loops
|
||||
|
||||
### Release version flow
|
||||
|
||||
Version bumps happen at specific release events:
|
||||
|
||||
| Event | Bump | Example |
|
||||
|-------|------|---------|
|
||||
| Feature merged to dev | Patch bump after dev release | `02.09.01-dev` → release → `02.09.02-dev` |
|
||||
| Dev promoted to RC | Minor bump | `02.09.02-dev` → `02.10.00-rc` |
|
||||
| RC merged to main | Minor bump | `02.10.00-rc` → `02.11.00` (stable) |
|
||||
| Dev recreated from main | Patch bump | `02.11.00` → `02.11.01-dev` |
|
||||
|
||||
### Release stream copies
|
||||
|
||||
When a higher-stability release is published, copies are created for all lesser streams with the same base version:
|
||||
|
||||
- **RC `02.10.00-rc`** also creates: `02.10.00-dev`, `02.10.00-alpha`, `02.10.00-beta`
|
||||
- **Stable `02.11.00`** also creates: `02.11.00-dev`, `02.11.00-alpha`, `02.11.00-beta`, `02.11.00-rc`
|
||||
|
||||
This ensures Joomla sites on ANY stability channel see the update (Joomla only shows versions higher than what's installed).
|
||||
|
||||
### Version files
|
||||
|
||||
The version tools update all files containing version stamps:
|
||||
|
||||
+3
-194
@@ -1,6 +1,5 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
@@ -10,199 +9,9 @@
|
||||
* INGROUP: moko-platform
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
|
||||
* PATH: /cli/release_cascade.php
|
||||
* BRIEF: Delete lesser pre-release channels from Gitea when promoting stability
|
||||
*
|
||||
* Usage:
|
||||
* php release_cascade.php --stability stable --token TOKEN --api-base URL
|
||||
* php release_cascade.php --stability rc --token TOKEN --api-base URL
|
||||
* php release_cascade.php --stability stable --version 09.01.00 --token TOKEN --api-base URL
|
||||
*
|
||||
* Cascade rules:
|
||||
* stable -> deletes development, alpha, beta, release-candidate
|
||||
* rc -> deletes development, alpha, beta
|
||||
* beta -> deletes development, alpha
|
||||
* alpha -> deletes development
|
||||
*
|
||||
* When --version is given, also deletes releases on any channel whose version
|
||||
* is lower than the specified version (prevents stale pre-releases lingering).
|
||||
* VERSION: 02.00.00
|
||||
* BRIEF: DEPRECATED — cascade behavior removed. Each release stream is independent.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
$stability = null;
|
||||
$token = null;
|
||||
$apiBase = null;
|
||||
$version = null;
|
||||
|
||||
foreach ($argv as $i => $arg) {
|
||||
if ($arg === '--stability' && isset($argv[$i + 1])) {
|
||||
$stability = $argv[$i + 1];
|
||||
}
|
||||
if ($arg === '--token' && isset($argv[$i + 1])) {
|
||||
$token = $argv[$i + 1];
|
||||
}
|
||||
if ($arg === '--api-base' && isset($argv[$i + 1])) {
|
||||
$apiBase = $argv[$i + 1];
|
||||
}
|
||||
if ($arg === '--version' && isset($argv[$i + 1])) {
|
||||
$version = $argv[$i + 1];
|
||||
}
|
||||
}
|
||||
|
||||
// Allow token from environment
|
||||
if ($token === null) {
|
||||
$token = getenv('MOKOGITEA_TOKEN') ?: getenv('GITEA_TOKEN') ?: null;
|
||||
}
|
||||
|
||||
if ($stability === null || $token === null || $apiBase === null) {
|
||||
fwrite(STDERR, "Usage: release_cascade.php --stability [stable|rc|beta|alpha] --token TOKEN --api-base URL\n");
|
||||
fwrite(STDERR, " --api-base: e.g. https://git.mokoconsulting.tech/api/v1/repos/Org/Repo\n");
|
||||
fwrite(STDERR, " Token can also be set via MOKOGITEA_TOKEN or GITEA_TOKEN env var\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Define cascade hierarchy
|
||||
$cascadeMap = [
|
||||
'stable' => ['development', 'alpha', 'beta', 'release-candidate'],
|
||||
'release-candidate' => ['development', 'alpha', 'beta'],
|
||||
'rc' => ['development', 'alpha', 'beta'],
|
||||
'beta' => ['development', 'alpha'],
|
||||
'alpha' => ['development'],
|
||||
];
|
||||
|
||||
if (!isset($cascadeMap[$stability])) {
|
||||
fwrite(STDERR, "Unknown stability level: {$stability}\n");
|
||||
fwrite(STDERR, "Valid options: stable, rc, beta, alpha\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$tagsToDelete = $cascadeMap[$stability];
|
||||
$deleted = 0;
|
||||
|
||||
foreach ($tagsToDelete as $tag) {
|
||||
// Get release by tag
|
||||
$ch = curl_init("{$apiBase}/releases/tags/{$tag}");
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => ["Authorization: token {$token}"],
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
]);
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
if ($httpCode !== 200 || empty($response)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data = json_decode($response, true);
|
||||
$releaseId = $data['id'] ?? null;
|
||||
|
||||
if ($releaseId === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Delete release
|
||||
$ch = curl_init("{$apiBase}/releases/{$releaseId}");
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_CUSTOMREQUEST => 'DELETE',
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => ["Authorization: token {$token}"],
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
]);
|
||||
curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
// Delete tag
|
||||
$ch = curl_init("{$apiBase}/tags/{$tag}");
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_CUSTOMREQUEST => 'DELETE',
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => ["Authorization: token {$token}"],
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
]);
|
||||
curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
echo "Deleted: {$tag} (release id: {$releaseId})\n";
|
||||
$deleted++;
|
||||
}
|
||||
|
||||
// ── Version-aware cleanup: delete releases with lesser version numbers ───────
|
||||
if ($version !== null) {
|
||||
// Normalize version for comparison (strip any suffix)
|
||||
$baseVersion = preg_replace('/(-(dev|alpha|beta|rc))+$/', '', $version);
|
||||
|
||||
// Check all channels (including ones not in the cascade map for this stability)
|
||||
$allChannels = ['development', 'alpha', 'beta', 'release-candidate', 'stable'];
|
||||
foreach ($allChannels as $tag) {
|
||||
// Skip the current stability channel
|
||||
if ($tag === $stability) {
|
||||
continue;
|
||||
}
|
||||
// Skip channels already deleted by cascade above
|
||||
if (in_array($tag, $tagsToDelete, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ch = curl_init("{$apiBase}/releases/tags/{$tag}");
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => ["Authorization: token {$token}"],
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
]);
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
if ($httpCode !== 200 || empty($response)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data = json_decode($response, true);
|
||||
$releaseId = $data['id'] ?? null;
|
||||
$releaseName = $data['name'] ?? '';
|
||||
if ($releaseId === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Extract version from release name (e.g. "element 09.00.01 (development)")
|
||||
$releaseVersion = null;
|
||||
if (preg_match('/(\d{2}\.\d{2}\.\d{2})/', $releaseName, $vm)) {
|
||||
$releaseVersion = $vm[1];
|
||||
}
|
||||
|
||||
if ($releaseVersion === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Delete if release version is less than the promoted version
|
||||
if (version_compare($releaseVersion, $baseVersion, '<')) {
|
||||
$delCh = curl_init("{$apiBase}/releases/{$releaseId}");
|
||||
curl_setopt_array($delCh, [
|
||||
CURLOPT_CUSTOMREQUEST => 'DELETE',
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => ["Authorization: token {$token}"],
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
]);
|
||||
curl_exec($delCh);
|
||||
curl_close($delCh);
|
||||
|
||||
$tagCh = curl_init("{$apiBase}/tags/{$tag}");
|
||||
curl_setopt_array($tagCh, [
|
||||
CURLOPT_CUSTOMREQUEST => 'DELETE',
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => ["Authorization: token {$token}"],
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
]);
|
||||
curl_exec($tagCh);
|
||||
curl_close($tagCh);
|
||||
|
||||
echo "Deleted: {$tag} — version {$releaseVersion} < {$baseVersion}\n";
|
||||
$deleted++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo "Cleaned up {$deleted} pre-release channel(s)\n";
|
||||
echo "release_cascade.php: No-op (cascade behavior removed — each stream is independent)\n";
|
||||
exit(0);
|
||||
|
||||
@@ -0,0 +1,275 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* FILE INFORMATION
|
||||
* DEFGROUP: moko-platform.CLI
|
||||
* INGROUP: moko-platform
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
|
||||
* PATH: /cli/release_publish.php
|
||||
* VERSION: 01.00.00
|
||||
* BRIEF: Publish a release and create copies for all lesser stability streams.
|
||||
*
|
||||
* When a release is published at a given stability, copies are created for all
|
||||
* lower stability streams with the same base version and their respective suffix.
|
||||
* updates.xml is updated for ALL streams and synced to ALL branches.
|
||||
*
|
||||
* Usage:
|
||||
* php release_publish.php --path . --stability stable --token TOKEN
|
||||
* php release_publish.php --path . --stability rc --token TOKEN --bump minor
|
||||
* php release_publish.php --path . --stability dev --token TOKEN --bump patch
|
||||
* php release_publish.php --path . --stability stable --token TOKEN --dry-run
|
||||
*
|
||||
* Options:
|
||||
* --path Repository root (default: .)
|
||||
* --stability Target stability: dev|alpha|beta|rc|stable (required)
|
||||
* --token Gitea API token (required)
|
||||
* --bump Version bump type before release: patch|minor|none (default: none)
|
||||
* --branch Current branch (default: auto-detect)
|
||||
* --gitea-url Gitea URL (default: env GITEA_URL)
|
||||
* --org Organization (default: env GITEA_ORG)
|
||||
* --repo Repository name (default: env GITEA_REPO)
|
||||
* --dry-run Preview without making changes
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
$path = '.';
|
||||
$stability = '';
|
||||
$token = '';
|
||||
$bumpType = 'none';
|
||||
$branch = '';
|
||||
$giteaUrl = getenv('GITEA_URL') ?: 'https://git.mokoconsulting.tech';
|
||||
$org = getenv('GITEA_ORG') ?: '';
|
||||
$repo = getenv('GITEA_REPO') ?: '';
|
||||
$dryRun = false;
|
||||
|
||||
foreach ($argv as $i => $arg) {
|
||||
if ($arg === '--path' && isset($argv[$i + 1])) $path = $argv[$i + 1];
|
||||
if ($arg === '--stability' && isset($argv[$i + 1])) $stability = $argv[$i + 1];
|
||||
if ($arg === '--token' && isset($argv[$i + 1])) $token = $argv[$i + 1];
|
||||
if ($arg === '--bump' && isset($argv[$i + 1])) $bumpType = $argv[$i + 1];
|
||||
if ($arg === '--branch' && isset($argv[$i + 1])) $branch = $argv[$i + 1];
|
||||
if ($arg === '--gitea-url' && isset($argv[$i + 1])) $giteaUrl = $argv[$i + 1];
|
||||
if ($arg === '--org' && isset($argv[$i + 1])) $org = $argv[$i + 1];
|
||||
if ($arg === '--repo' && isset($argv[$i + 1])) $repo = $argv[$i + 1];
|
||||
if ($arg === '--dry-run') $dryRun = true;
|
||||
}
|
||||
|
||||
if (empty($stability) || empty($token)) {
|
||||
fwrite(STDERR, "Usage: release_publish.php --stability <dev|alpha|beta|rc|stable> --token TOKEN [options]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$cli = __DIR__;
|
||||
$php = PHP_BINARY;
|
||||
$giteaUrl = rtrim($giteaUrl, '/');
|
||||
|
||||
// Auto-detect org/repo from git remote if not set
|
||||
if (empty($org) || empty($repo)) {
|
||||
$remote = trim((string) @shell_exec("cd " . escapeshellarg($path) . " && git remote get-url origin 2>/dev/null"));
|
||||
if (preg_match('#/([^/]+)/([^/.]+?)(?:\.git)?$#', $remote, $m)) {
|
||||
if (empty($org)) $org = $m[1];
|
||||
if (empty($repo)) $repo = $m[2];
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-detect branch
|
||||
if (empty($branch)) {
|
||||
$branch = getenv('GITHUB_REF_NAME') ?: trim((string) @shell_exec("cd " . escapeshellarg($path) . " && git rev-parse --abbrev-ref HEAD 2>/dev/null"));
|
||||
}
|
||||
|
||||
$apiBase = "{$giteaUrl}/api/v1/repos/{$org}/{$repo}";
|
||||
|
||||
// Stability ordering and suffix mapping
|
||||
$allStabilities = ['dev', 'alpha', 'beta', 'rc', 'stable'];
|
||||
$suffixMap = [
|
||||
'dev' => '-dev',
|
||||
'alpha' => '-alpha',
|
||||
'beta' => '-beta',
|
||||
'rc' => '-rc',
|
||||
'stable' => '',
|
||||
];
|
||||
$releaseTagMap = [
|
||||
'dev' => 'development',
|
||||
'alpha' => 'alpha',
|
||||
'beta' => 'beta',
|
||||
'rc' => 'release-candidate',
|
||||
'stable' => 'stable',
|
||||
];
|
||||
|
||||
$stabilityIndex = array_search($stability, $allStabilities);
|
||||
if ($stabilityIndex === false) {
|
||||
fwrite(STDERR, "Invalid stability: {$stability}\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo "=== Release Publish ===\n";
|
||||
echo "Stability: {$stability} | Bump: {$bumpType} | Branch: {$branch}\n";
|
||||
echo "Repo: {$org}/{$repo}\n";
|
||||
|
||||
// -- Step 1: Version bump (if requested) --
|
||||
if ($bumpType !== 'none') {
|
||||
$bumpFlag = $bumpType === 'minor' ? '--minor' : '';
|
||||
echo "\n--- Step 1: Version bump ({$bumpType}) ---\n";
|
||||
if (!$dryRun) {
|
||||
passthru("{$php} {$cli}/version_bump.php --path " . escapeshellarg($path) . " {$bumpFlag} 2>&1");
|
||||
} else {
|
||||
echo "[DRY-RUN] Would run version_bump.php {$bumpFlag}\n";
|
||||
}
|
||||
}
|
||||
|
||||
// -- Step 2: Read version and set stability suffix --
|
||||
echo "\n--- Step 2: Set version suffix ---\n";
|
||||
$versionOutput = [];
|
||||
exec("{$php} {$cli}/version_read.php --path " . escapeshellarg($path) . " 2>/dev/null", $versionOutput);
|
||||
$version = trim($versionOutput[0] ?? '');
|
||||
if (empty($version)) {
|
||||
fwrite(STDERR, "No version found\n");
|
||||
exit(1);
|
||||
}
|
||||
// Strip existing suffix to get base version
|
||||
$baseVersion = preg_replace('/(-(dev|alpha|beta|rc))+$/', '', $version);
|
||||
|
||||
if (!$dryRun) {
|
||||
passthru("{$php} {$cli}/version_set_platform.php --path " . escapeshellarg($path)
|
||||
. " --version " . escapeshellarg($baseVersion)
|
||||
. " --branch " . escapeshellarg($branch)
|
||||
. " --stability " . escapeshellarg($stability) . " 2>&1");
|
||||
passthru("{$php} {$cli}/version_check.php --path " . escapeshellarg($path) . " --fix 2>/dev/null");
|
||||
}
|
||||
|
||||
$releaseVersion = $baseVersion . $suffixMap[$stability];
|
||||
echo "Release version: {$releaseVersion}\n";
|
||||
|
||||
// -- Step 3: Build release package --
|
||||
echo "\n--- Step 3: Build and upload release ---\n";
|
||||
$releaseTag = $releaseTagMap[$stability];
|
||||
$sha256 = '';
|
||||
|
||||
if (!$dryRun) {
|
||||
// Create release
|
||||
passthru("{$php} {$cli}/release_create.php --path " . escapeshellarg($path)
|
||||
. " --version " . escapeshellarg($releaseVersion)
|
||||
. " --tag " . escapeshellarg($releaseTag)
|
||||
. " --token " . escapeshellarg($token)
|
||||
. " --api-base " . escapeshellarg($apiBase)
|
||||
. " --repo " . escapeshellarg($repo)
|
||||
. " --branch " . escapeshellarg($branch) . " 2>&1");
|
||||
|
||||
// Build and upload package
|
||||
$packageOutput = [];
|
||||
exec("{$php} {$cli}/release_package.php --path " . escapeshellarg($path)
|
||||
. " --version " . escapeshellarg($releaseVersion)
|
||||
. " --tag " . escapeshellarg($releaseTag)
|
||||
. " --token " . escapeshellarg($token)
|
||||
. " --api-base " . escapeshellarg($apiBase)
|
||||
. " --repo " . escapeshellarg($repo)
|
||||
. " --output /tmp 2>&1", $packageOutput);
|
||||
foreach ($packageOutput as $line) {
|
||||
echo $line . "\n";
|
||||
// Extract SHA from output
|
||||
if (preg_match('/sha256_zip=([a-f0-9]{64})/i', $line, $m)) {
|
||||
$sha256 = $m[1];
|
||||
}
|
||||
}
|
||||
// Also check GITHUB_OUTPUT
|
||||
$ghOutput = getenv('GITHUB_OUTPUT');
|
||||
if ($ghOutput && file_exists($ghOutput)) {
|
||||
$ghContent = file_get_contents($ghOutput);
|
||||
if (preg_match('/sha256_zip=([a-f0-9]{64})/i', $ghContent, $m)) {
|
||||
$sha256 = $m[1];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo "[DRY-RUN] Would build and upload {$releaseVersion} to {$releaseTag}\n";
|
||||
}
|
||||
|
||||
// -- Step 4: Create copies for all lesser stability streams --
|
||||
echo "\n--- Step 4: Create copies for lesser streams ---\n";
|
||||
for ($i = 0; $i < $stabilityIndex; $i++) {
|
||||
$lesserStability = $allStabilities[$i];
|
||||
$lesserTag = $releaseTagMap[$lesserStability];
|
||||
$lesserVersion = $baseVersion . $suffixMap[$lesserStability];
|
||||
|
||||
echo " Creating {$lesserStability} release: {$lesserVersion}\n";
|
||||
|
||||
if (!$dryRun) {
|
||||
// Create or update the lesser release with the same package
|
||||
passthru("{$php} {$cli}/release_create.php --path " . escapeshellarg($path)
|
||||
. " --version " . escapeshellarg($lesserVersion)
|
||||
. " --tag " . escapeshellarg($lesserTag)
|
||||
. " --token " . escapeshellarg($token)
|
||||
. " --api-base " . escapeshellarg($apiBase)
|
||||
. " --repo " . escapeshellarg($repo)
|
||||
. " --branch " . escapeshellarg($branch) . " 2>&1");
|
||||
|
||||
// Upload the same package to the lesser release
|
||||
passthru("{$php} {$cli}/release_package.php --path " . escapeshellarg($path)
|
||||
. " --version " . escapeshellarg($lesserVersion)
|
||||
. " --tag " . escapeshellarg($lesserTag)
|
||||
. " --token " . escapeshellarg($token)
|
||||
. " --api-base " . escapeshellarg($apiBase)
|
||||
. " --repo " . escapeshellarg($repo)
|
||||
. " --output /tmp 2>&1");
|
||||
}
|
||||
}
|
||||
|
||||
// -- Step 5: Update ALL streams in updates.xml --
|
||||
echo "\n--- Step 5: Update updates.xml for ALL streams ---\n";
|
||||
// Write entry for the primary stream and all lesser streams
|
||||
$streamsToWrite = array_slice($allStabilities, 0, $stabilityIndex + 1);
|
||||
|
||||
foreach ($streamsToWrite as $stream) {
|
||||
$streamVersion = $baseVersion . $suffixMap[$stream];
|
||||
$shaFlag = !empty($sha256) ? "--sha {$sha256}" : '';
|
||||
|
||||
echo " Writing {$stream} stream: {$streamVersion}\n";
|
||||
if (!$dryRun) {
|
||||
passthru("{$php} {$cli}/updates_xml_build.php --path " . escapeshellarg($path)
|
||||
. " --version " . escapeshellarg($streamVersion)
|
||||
. " --stability " . escapeshellarg($stream)
|
||||
. " --gitea-url " . escapeshellarg($giteaUrl)
|
||||
. " --org " . escapeshellarg($org)
|
||||
. " --repo " . escapeshellarg($repo)
|
||||
. " {$shaFlag} 2>&1");
|
||||
}
|
||||
}
|
||||
|
||||
// -- Step 6: Commit updates.xml and sync to all branches --
|
||||
echo "\n--- Step 6: Commit and sync updates.xml ---\n";
|
||||
$root = realpath($path) ?: $path;
|
||||
|
||||
if (!$dryRun) {
|
||||
$diffCheck = trim((string) @shell_exec("cd " . escapeshellarg($root) . " && git diff --quiet updates.xml 2>&1 && echo clean || echo dirty"));
|
||||
if ($diffCheck === 'dirty') {
|
||||
@shell_exec("cd " . escapeshellarg($root) . " && git add updates.xml");
|
||||
@shell_exec("cd " . escapeshellarg($root) . " && git commit -m " . escapeshellarg("chore: update channels for {$releaseVersion} [skip ci]")
|
||||
. " --author=\"gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>\"");
|
||||
@shell_exec("cd " . escapeshellarg($root) . " && git push origin " . escapeshellarg($branch) . " 2>&1");
|
||||
echo " Committed updates.xml\n";
|
||||
}
|
||||
|
||||
// Sync to all branches
|
||||
passthru("{$php} {$cli}/updates_xml_sync.php --path " . escapeshellarg($path)
|
||||
. " --current " . escapeshellarg($branch) . " --all"
|
||||
. " --version " . escapeshellarg($releaseVersion)
|
||||
. " --token " . escapeshellarg($token)
|
||||
. " --gitea-url " . escapeshellarg($giteaUrl)
|
||||
. " --org " . escapeshellarg($org)
|
||||
. " --repo " . escapeshellarg($repo) . " 2>&1");
|
||||
} else {
|
||||
echo "[DRY-RUN] Would commit updates.xml and sync to all branches\n";
|
||||
}
|
||||
|
||||
echo "\n=== Release published: {$releaseVersion} ===\n";
|
||||
|
||||
// Output for CI
|
||||
$ghOutput = getenv('GITHUB_OUTPUT');
|
||||
if ($ghOutput) {
|
||||
file_put_contents($ghOutput, "version={$releaseVersion}\nbase_version={$baseVersion}\n", FILE_APPEND);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
+32
-71
@@ -413,63 +413,35 @@ function buildEntry(
|
||||
return implode("\n", $lines);
|
||||
}
|
||||
|
||||
// -- Determine which channels to write ----------------------------------------
|
||||
// Stable cascades to all channels; pre-releases cascade down to lower channels.
|
||||
// Each channel entry represents "latest release available at this stability or higher".
|
||||
// When stable releases, ALL channels point to stable (it's the newest for everyone).
|
||||
// When RC releases, rc/beta/alpha/dev point to RC; stable is preserved.
|
||||
// When dev releases, only dev is updated; everything else is preserved.
|
||||
$allChannels = ['development', 'alpha', 'beta', 'rc', 'stable'];
|
||||
$stabilityIndex = array_search($stability === 'development' ? 'development' : $stability, $allChannels);
|
||||
if ($stabilityIndex === false) {
|
||||
$stabilityIndex = 4; // default to stable
|
||||
}
|
||||
|
||||
// Write entries for the current channel AND all lower channels (cascade down)
|
||||
// All cascaded entries point to the CURRENT release (the highest stability being built)
|
||||
// -- Write ONLY the single channel being released --------------------------------
|
||||
// No cascading. Each update stream is independent.
|
||||
// When dev releases, only the dev entry is written/updated.
|
||||
// When stable releases, only the stable entry is written/updated.
|
||||
// All other channel entries are preserved exactly as-is.
|
||||
$entries = [];
|
||||
$giteaTag = $releaseTagMap[$stability] ?? $stability;
|
||||
$channelVersion = $version . ($stabilitySuffixMap[$stability] ?? '');
|
||||
$channelDownloadUrl = "{$giteaUrl}/{$org}/{$repo}/releases/download/{$giteaTag}/{$typePrefix}{$extElement}-{$channelVersion}.zip";
|
||||
$channelInfoUrl = "{$giteaUrl}/{$org}/{$repo}/releases/tag/{$giteaTag}";
|
||||
$joomlaTag = $stabilityTagMap[$stability] ?? $stability;
|
||||
$changelogUrl = "{$giteaUrl}/{$org}/{$repo}/raw/branch/main/CHANGELOG.md";
|
||||
|
||||
// Stability labels for descriptions
|
||||
$stabilityLabelMap = [
|
||||
'stable' => 'stable',
|
||||
'rc' => 'rc',
|
||||
'beta' => 'beta',
|
||||
'alpha' => 'alpha',
|
||||
'development' => 'development',
|
||||
];
|
||||
|
||||
for ($i = 0; $i <= $stabilityIndex; $i++) {
|
||||
$channelName = $allChannels[$i];
|
||||
$joomlaTag = $stabilityTagMap[$channelName] ?? $channelName;
|
||||
$stabilityLabel = $stabilityLabelMap[$channelName] ?? $channelName;
|
||||
|
||||
// All cascaded entries use the SAME version as the highest-stability package.
|
||||
// The version MUST match what's inside the ZIP (Joomla reads it post-install).
|
||||
// The <tag> differentiates channels; the version is always the release version.
|
||||
// Changelog URL: points to the CHANGELOG.md on main branch
|
||||
$changelogUrl = "{$giteaUrl}/{$org}/{$repo}/raw/branch/main/CHANGELOG.md";
|
||||
|
||||
$entries[] = buildEntry(
|
||||
$joomlaTag,
|
||||
$entryVersion,
|
||||
$channelDownloadUrl,
|
||||
$displayName,
|
||||
$stabilityLabel,
|
||||
$extElement,
|
||||
$extType,
|
||||
$clientTag,
|
||||
$folderTag,
|
||||
$channelInfoUrl,
|
||||
$targetPlatform,
|
||||
$phpTag,
|
||||
$shaTag,
|
||||
$changelogUrl
|
||||
);
|
||||
}
|
||||
$entries[] = buildEntry(
|
||||
$joomlaTag,
|
||||
$channelVersion,
|
||||
$channelDownloadUrl,
|
||||
$displayName,
|
||||
$stability,
|
||||
$extElement,
|
||||
$extType,
|
||||
$clientTag,
|
||||
$folderTag,
|
||||
$channelInfoUrl,
|
||||
$targetPlatform,
|
||||
$phpTag,
|
||||
$shaTag,
|
||||
$changelogUrl
|
||||
);
|
||||
|
||||
// -- Preserve existing entries for channels not being updated -----------------
|
||||
$dest = $outputFile ?? "{$root}/updates.xml";
|
||||
@@ -478,32 +450,21 @@ $preservedEntries = [];
|
||||
if (file_exists($dest)) {
|
||||
$existingXml = @simplexml_load_file($dest);
|
||||
if ($existingXml) {
|
||||
// Joomla tags we're writing — don't preserve these
|
||||
$writtenChannels = [];
|
||||
for ($i = 0; $i <= $stabilityIndex; $i++) {
|
||||
$writtenChannels[] = $stabilityTagMap[$allChannels[$i]] ?? $allChannels[$i];
|
||||
}
|
||||
// Also match legacy/alternate tag names (e.g. 'development' = 'dev')
|
||||
$writtenChannels[] = 'development'; // alias for 'dev'
|
||||
// Only the channel we're writing gets replaced — everything else is preserved
|
||||
$writtenTag = $joomlaTag;
|
||||
// Also match legacy alternate (e.g. 'development' = 'dev')
|
||||
$writtenAliases = [$writtenTag];
|
||||
if ($writtenTag === 'dev') $writtenAliases[] = 'development';
|
||||
if ($writtenTag === 'development') $writtenAliases[] = 'dev';
|
||||
|
||||
foreach ($existingXml->update as $existingUpdate) {
|
||||
$existingTag = '';
|
||||
if (isset($existingUpdate->tags->tag)) {
|
||||
$existingTag = (string) $existingUpdate->tags->tag;
|
||||
}
|
||||
$existingVersion = (string) ($existingUpdate->version ?? '');
|
||||
// Strip suffixes for comparison
|
||||
$existingBase = preg_replace('/(-(dev|alpha|beta|rc))+$/', '', $existingVersion);
|
||||
$currentBase = preg_replace('/(-(dev|alpha|beta|rc))+$/', '', $version);
|
||||
|
||||
// Keep entries for channels we're NOT overwriting,
|
||||
// but ONLY if their version is >= current (never preserve stale entries)
|
||||
if (!empty($existingTag) && !in_array($existingTag, $writtenChannels, true)) {
|
||||
if (version_compare($existingBase, $currentBase, '>=')) {
|
||||
$preservedEntries[] = ' ' . trim($existingUpdate->asXML());
|
||||
} else {
|
||||
echo "Discarding stale {$existingTag} entry (v{$existingVersion} < v{$version})\n";
|
||||
}
|
||||
// Keep ALL entries except the one channel we're overwriting
|
||||
if (!empty($existingTag) && !in_array($existingTag, $writtenAliases, true)) {
|
||||
$preservedEntries[] = ' ' . trim($existingUpdate->asXML());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,12 @@
|
||||
*
|
||||
* Usage:
|
||||
* php updates_xml_sync.php --path /repo --branches main,dev --current dev
|
||||
* php updates_xml_sync.php --path /repo --branches main --current dev --version 02.01.27
|
||||
* php updates_xml_sync.php --path /repo --all --current dev --version 02.01.27
|
||||
*
|
||||
* Options:
|
||||
* --path Repository root containing updates.xml (default: .)
|
||||
* --branches Comma-separated target branches to sync to (default: main,dev)
|
||||
* --all Auto-discover all branches via Gitea API (overrides --branches)
|
||||
* --current Current branch to skip (required)
|
||||
* --version Version string for commit message (optional)
|
||||
* --token Gitea API token (default: env MOKOGITEA_TOKEN)
|
||||
@@ -41,10 +42,12 @@ $token = getenv('MOKOGITEA_TOKEN') ?: '';
|
||||
$giteaUrl = getenv('GITEA_URL') ?: 'https://git.mokoconsulting.tech';
|
||||
$org = getenv('GITEA_ORG') ?: '';
|
||||
$repo = getenv('GITEA_REPO') ?: '';
|
||||
$discoverAll = false;
|
||||
|
||||
foreach ($argv as $i => $arg) {
|
||||
if ($arg === '--path' && isset($argv[$i + 1])) $path = $argv[$i + 1];
|
||||
if ($arg === '--branches' && isset($argv[$i + 1])) $branches = $argv[$i + 1];
|
||||
if ($arg === '--all') $discoverAll = true;
|
||||
if ($arg === '--current' && isset($argv[$i + 1])) $current = $argv[$i + 1];
|
||||
if ($arg === '--version' && isset($argv[$i + 1])) $version = $argv[$i + 1];
|
||||
if ($arg === '--token' && isset($argv[$i + 1])) $token = $argv[$i + 1];
|
||||
@@ -68,6 +71,35 @@ if ($org === '' || $repo === '') {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Auto-discover branches if --all flag is set
|
||||
if ($discoverAll) {
|
||||
$apiUrl = "{$giteaUrl}/api/v1/repos/{$org}/{$repo}/branches?limit=50";
|
||||
$ch = curl_init($apiUrl);
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => ["Authorization: token {$token}", 'Accept: application/json'],
|
||||
CURLOPT_TIMEOUT => 15,
|
||||
]);
|
||||
$response = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
$branchList = json_decode($response ?: '[]', true) ?: [];
|
||||
$discovered = [];
|
||||
foreach ($branchList as $b) {
|
||||
$name = $b['name'] ?? '';
|
||||
if ($name !== '' && $name !== $current
|
||||
&& !str_starts_with($name, 'version/')
|
||||
&& !str_starts_with($name, 'feature/')
|
||||
&& !str_starts_with($name, 'patch/')
|
||||
) {
|
||||
$discovered[] = $name;
|
||||
}
|
||||
}
|
||||
if (!empty($discovered)) {
|
||||
$branches = implode(',', $discovered);
|
||||
echo "Discovered branches: {$branches}\n";
|
||||
}
|
||||
}
|
||||
|
||||
$updatesFile = rtrim($path, '/') . '/updates.xml';
|
||||
if (!file_exists($updatesFile)) {
|
||||
fwrite(STDERR, "No updates.xml found at {$updatesFile}\n");
|
||||
|
||||
@@ -53,7 +53,7 @@ $stabilityMap = [
|
||||
|
||||
if (array_key_exists($branch, $stabilityMap)) {
|
||||
$stability = $stabilityMap[$branch];
|
||||
} elseif (str_starts_with($branch, 'feature/')) {
|
||||
} elseif (str_starts_with($branch, 'feature/') || str_starts_with($branch, 'patch/')) {
|
||||
$stability = 'dev';
|
||||
} else {
|
||||
$stability = 'dev';
|
||||
@@ -62,8 +62,8 @@ if (array_key_exists($branch, $stabilityMap)) {
|
||||
$cli = __DIR__;
|
||||
$php = PHP_BINARY;
|
||||
|
||||
// Step 1: Patch bump (skip on alpha/beta/rc — those only change the suffix)
|
||||
$shouldBump = !in_array($branch, ['alpha', 'beta', 'rc'], true);
|
||||
// Step 1: Patch bump — all branches get patch bumps
|
||||
$shouldBump = true;
|
||||
|
||||
if ($shouldBump) {
|
||||
$bumpOutput = [];
|
||||
|
||||
Reference in New Issue
Block a user