Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a1cba42f43 | |||
| 9eef484585 | |||
| ff14a1dcba | |||
| 925b27f2dc | |||
| 4e519b4e7c | |||
| 118c1cbe2f | |||
| 05aec9b315 | |||
| b345e42cd0 | |||
| f99e39efa3 | |||
| ae5e1f48dd | |||
| 2ddd6c27cd | |||
| 362e75a9a8 | |||
| cb4c227853 | |||
| b8e8487f6b | |||
| 7abe3ef035 | |||
| 344881809d |
@@ -5,7 +5,7 @@
|
|||||||
# FILE INFORMATION
|
# FILE INFORMATION
|
||||||
# DEFGROUP: MokoGitea.Workflow
|
# DEFGROUP: MokoGitea.Workflow
|
||||||
# INGROUP: MokoCLI.Release
|
# INGROUP: MokoCLI.Release
|
||||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
|
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||||
# PATH: /.mokogitea/workflows/auto-bump.yml
|
# PATH: /.mokogitea/workflows/auto-bump.yml
|
||||||
# VERSION: 09.02.00
|
# VERSION: 09.02.00
|
||||||
# BRIEF: Auto patch-bump version on every push to dev (skips merge commits)
|
# BRIEF: Auto patch-bump version on every push to dev (skips merge commits)
|
||||||
@@ -34,8 +34,7 @@ jobs:
|
|||||||
if: >-
|
if: >-
|
||||||
!contains(github.event.head_commit.message, '[skip ci]') &&
|
!contains(github.event.head_commit.message, '[skip ci]') &&
|
||||||
!contains(github.event.head_commit.message, '[skip bump]') &&
|
!contains(github.event.head_commit.message, '[skip bump]') &&
|
||||||
!startsWith(github.event.head_commit.message, 'Merge pull request') &&
|
!startsWith(github.event.head_commit.message, 'Merge pull request')
|
||||||
!startsWith(github.event.repository.name, 'Template-')
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
|||||||
@@ -5,16 +5,16 @@
|
|||||||
# FILE INFORMATION
|
# FILE INFORMATION
|
||||||
# DEFGROUP: MokoGitea.Workflow
|
# DEFGROUP: MokoGitea.Workflow
|
||||||
# INGROUP: MokoCLI.Release
|
# INGROUP: MokoCLI.Release
|
||||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
|
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||||
# PATH: /.mokogitea/workflows/auto-release.yml
|
# PATH: /templates/workflows/universal/auto-release.yml.template
|
||||||
# VERSION: 05.01.00
|
# VERSION: 05.01.00
|
||||||
# BRIEF: Universal build & release � detects platform from metadata API
|
# BRIEF: Universal build & release � detects platform from MokoGitea repo metadata (API)
|
||||||
#
|
#
|
||||||
# +=======================================================================+
|
# +=======================================================================+
|
||||||
# | UNIVERSAL BUILD & RELEASE PIPELINE |
|
# | UNIVERSAL BUILD & RELEASE PIPELINE |
|
||||||
# +=======================================================================+
|
# +=======================================================================+
|
||||||
# | |
|
# | |
|
||||||
# | Reads metadata API (joomla|dolibarr|generic) to branch logic. |
|
# | Reads MokoGitea repo metadata (joomla|dolibarr|generic) to branch logic. |
|
||||||
# | |
|
# | |
|
||||||
# | Platform-specific: |
|
# | Platform-specific: |
|
||||||
# | joomla: XML manifest, type-prefixed packages |
|
# | joomla: XML manifest, type-prefixed packages |
|
||||||
@@ -104,36 +104,11 @@ jobs:
|
|||||||
|
|
||||||
- name: Rename branch to rc
|
- name: Rename branch to rc
|
||||||
run: |
|
run: |
|
||||||
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
php ${MOKO_CLI}/branch_rename.php \
|
||||||
AUTH="Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}"
|
--from "${{ github.event.pull_request.head.ref || 'dev' }}" --to rc \
|
||||||
FROM="${{ github.event.pull_request.head.ref || 'dev' }}"
|
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
|
||||||
PR="${{ github.event.pull_request.number }}"
|
--api-base "${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" \
|
||||||
|
--pr "${{ github.event.pull_request.number }}"
|
||||||
# Resolve the source branch HEAD commit.
|
|
||||||
SRC_JSON=$(curl -sf -H "$AUTH" "${API_BASE}/branches/${FROM}") \
|
|
||||||
|| { echo "::error::Source branch ${FROM} not found"; exit 1; }
|
|
||||||
SRC_SHA=$(printf '%s' "$SRC_JSON" | python3 -c "import sys, json; print(json.load(sys.stdin)['commit']['id'])" 2>/dev/null || true)
|
|
||||||
[ -n "$SRC_SHA" ] || { echo "::error::Could not resolve HEAD of ${FROM}"; exit 1; }
|
|
||||||
|
|
||||||
# Point rc at the source commit via git push. Gitea's git/refs PATCH API
|
|
||||||
# returns HTTP 405 on ANY protected branch (force or not, even for a user in
|
|
||||||
# the force-push allowlist), so it cannot move a protected rc. git push honors
|
|
||||||
# the push + force-push allowlists and creates rc if it is absent.
|
|
||||||
PUSH_URL="https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@${MOKOGITEA_URL#https://}/${GITEA_ORG}/${GITEA_REPO}.git"
|
|
||||||
git config --global user.name "mokogitea-actions[bot]"
|
|
||||||
git config --global user.email "actions@mokoconsulting.tech"
|
|
||||||
git fetch --no-tags "$PUSH_URL" "${FROM}"
|
|
||||||
git push --force "$PUSH_URL" "FETCH_HEAD:refs/heads/rc" \
|
|
||||||
|| { echo "::error::Failed to point rc at ${FROM} (${SRC_SHA}) via git push"; exit 1; }
|
|
||||||
echo "rc set to ${FROM} (${SRC_SHA})"
|
|
||||||
|
|
||||||
# Repoint the PR at rc, then delete the old source branch (non-fatal).
|
|
||||||
if [ -n "$PR" ]; then
|
|
||||||
curl -s -X PATCH -H "$AUTH" -H "Content-Type: application/json" \
|
|
||||||
"${API_BASE}/pulls/${PR}" -d '{"head":"rc"}' >/dev/null || true
|
|
||||||
fi
|
|
||||||
curl -s -X DELETE -H "$AUTH" "${API_BASE}/branches/${FROM}" >/dev/null || true
|
|
||||||
echo "Renamed ${FROM} -> rc"
|
|
||||||
|
|
||||||
- name: Checkout rc and configure git
|
- name: Checkout rc and configure git
|
||||||
run: |
|
run: |
|
||||||
@@ -374,47 +349,13 @@ jobs:
|
|||||||
if [ -n "$VERSION" ] && [ -f "CHANGELOG.md" ]; then
|
if [ -n "$VERSION" ] && [ -f "CHANGELOG.md" ]; then
|
||||||
DATE=$(date +%Y-%m-%d)
|
DATE=$(date +%Y-%m-%d)
|
||||||
python3 -c "
|
python3 -c "
|
||||||
import sys, re
|
import sys
|
||||||
version, date = sys.argv[1], sys.argv[2]
|
version, date = sys.argv[1], sys.argv[2]
|
||||||
lines = open('CHANGELOG.md').read().split('\n')
|
content = open('CHANGELOG.md').read()
|
||||||
h2 = re.compile(r'^##\s+\[([^\]]+)\]')
|
old = '## [Unreleased]'
|
||||||
header, sections, cur = [], [], None
|
new = f'## [Unreleased]\n\n## [{version}] --- {date}'
|
||||||
for ln in lines:
|
content = content.replace(old, new, 1)
|
||||||
m = h2.match(ln)
|
open('CHANGELOG.md', 'w').write(content)
|
||||||
if m:
|
|
||||||
if cur: sections.append(cur)
|
|
||||||
cur = {'label': m.group(1).strip(), 'head': ln, 'body': []}
|
|
||||||
elif cur is None:
|
|
||||||
header.append(ln)
|
|
||||||
else:
|
|
||||||
cur['body'].append(ln)
|
|
||||||
if cur: sections.append(cur)
|
|
||||||
def nonempty(b): return any(x.strip() for x in b)
|
|
||||||
def trim(b):
|
|
||||||
b = b[:]
|
|
||||||
while b and not b[0].strip(): b.pop(0)
|
|
||||||
while b and not b[-1].strip(): b.pop()
|
|
||||||
return b
|
|
||||||
unreleased, order, bykey = [], [], {}
|
|
||||||
for s in sections:
|
|
||||||
key = s['label'].lower()
|
|
||||||
if key == 'unreleased':
|
|
||||||
if nonempty(s['body']): unreleased += s['body']
|
|
||||||
continue
|
|
||||||
if not nonempty(s['body']): continue # drop blank release sections
|
|
||||||
if key in bykey: bykey[key]['body'] += [''] + s['body'] # merge duplicate heading (never drop content)
|
|
||||||
else: bykey[key] = s; order.append(key)
|
|
||||||
rest, seen = [bykey[k] for k in order], set(order)
|
|
||||||
out = []
|
|
||||||
htxt = '\n'.join(header).rstrip()
|
|
||||||
if htxt: out += [htxt, '']
|
|
||||||
out += ['## [Unreleased]', '']
|
|
||||||
promote = bool(unreleased) and version.lower() not in seen
|
|
||||||
if unreleased and not promote: out += trim(unreleased) + ['']
|
|
||||||
if promote: out += ['## [%s] --- %s' % (version, date), ''] + trim(unreleased) + ['']
|
|
||||||
for s in rest: out += [s['head'], ''] + trim(s['body']) + ['']
|
|
||||||
res = re.sub(r'\n{3,}', '\n\n', '\n'.join(out)).rstrip('\n') + '\n'
|
|
||||||
open('CHANGELOG.md', 'w').write(res)
|
|
||||||
" "$VERSION" "$DATE"
|
" "$VERSION" "$DATE"
|
||||||
git add CHANGELOG.md
|
git add CHANGELOG.md
|
||||||
git commit -m "chore: promote changelog [Unreleased] → [${VERSION}]" || true
|
git commit -m "chore: promote changelog [Unreleased] → [${VERSION}]" || true
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
# FILE INFORMATION
|
# FILE INFORMATION
|
||||||
# DEFGROUP: MokoGitea.Workflow
|
# DEFGROUP: MokoGitea.Workflow
|
||||||
# INGROUP: MokoCLI.Universal
|
# INGROUP: MokoCLI.Universal
|
||||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
|
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||||
# PATH: /.mokogitea/workflows/branch-cleanup.yml
|
# PATH: /.mokogitea/workflows/branch-cleanup.yml
|
||||||
# VERSION: 01.00.00
|
# VERSION: 01.00.00
|
||||||
# BRIEF: Delete feature branches after PR merge
|
# BRIEF: Delete feature branches after PR merge
|
||||||
|
|||||||
@@ -1,190 +1,65 @@
|
|||||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
#
|
|
||||||
# FILE INFORMATION
|
# FILE INFORMATION
|
||||||
# DEFGROUP: MokoGitea.Workflow
|
# DEFGROUP: MokoGitea.Workflow
|
||||||
# INGROUP: MokoCLI.Cascade
|
# INGROUP: MokoCLI.Release
|
||||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
|
# BRIEF: Reset dev to main after each release (cascade). Moved out of auto-release Step 11.
|
||||||
# PATH: /.mokogitea/workflows/cascade-dev.yml
|
#
|
||||||
# VERSION: 02.01.00
|
# +========================================================================+
|
||||||
# BRIEF: Cascade main -> dev; auto-merge clean, auto-resolve VERSION-stamp-only conflicts, else notify
|
# | CASCADE MAIN -> DEV |
|
||||||
|
# +========================================================================+
|
||||||
|
# | dev mirrors main and is reset on every release. |
|
||||||
|
# | delete+recreate cannot run against a protected branch, so this |
|
||||||
|
# | force-pushes main -> dev. The automation identity is force-push |
|
||||||
|
# | allowlisted on dev via branch-protection.yml. |
|
||||||
|
# | Runs AFTER the release workflow completes, so dev picks up the |
|
||||||
|
# | fully version-bumped + changelog-promoted main (not the pre-bump |
|
||||||
|
# | state). Force-push (not merge) => no version-file conflicts. |
|
||||||
|
# +========================================================================+
|
||||||
|
|
||||||
name: "Cascade Main -> Dev"
|
name: "Cascade Main -> Dev"
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
workflow_run:
|
||||||
branches:
|
workflows: ["Universal: Build & Release"]
|
||||||
- main
|
types: [completed]
|
||||||
# Daily safety net: catches drift even when main only received [skip ci] pushes
|
|
||||||
# (which never fire the push trigger above). Off-round minute to avoid a fleet-wide spike.
|
|
||||||
schedule:
|
|
||||||
- cron: '23 7 * * *'
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: cascade-dev-${{ github.repository }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
env:
|
|
||||||
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
|
||||||
# ntfy destination is configured via repo or org variables (org vars are inherited).
|
|
||||||
NTFY_URL: ${{ vars.NTFY_URL || 'https://ntfy.mokoconsulting.tech' }}
|
|
||||||
NTFY_TOPIC: ${{ vars.CASCADE_NTFY_TOPIC || vars.NTFY_TOPIC || 'gitea-releases' }}
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
cascade:
|
cascade:
|
||||||
name: Cascade main -> dev
|
name: Reset dev to main
|
||||||
|
if: >-
|
||||||
|
!startsWith(github.event.repository.name, 'Template-') &&
|
||||||
|
(github.event_name == 'workflow_dispatch' ||
|
||||||
|
github.event.workflow_run.conclusion == 'success')
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout (full history for merge/resolve)
|
- name: Force dev to main
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
|
||||||
|
|
||||||
- name: Cascade main -> dev (auto-resolve version stamps, else notify)
|
|
||||||
env:
|
env:
|
||||||
TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||||
|
SERVER: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||||
REPO: ${{ github.repository }}
|
REPO: ${{ github.repository }}
|
||||||
run: |
|
run: |
|
||||||
set -uo pipefail
|
set -euo pipefail
|
||||||
API="${MOKOGITEA_URL}/api/v1/repos/${REPO}"
|
git init -q sync && cd sync
|
||||||
AUTH="Authorization: token ${TOKEN}"
|
git config user.email "mokogitea-actions[bot]@mokoconsulting.tech"
|
||||||
jqget() { python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('$1',''))" 2>/dev/null; }
|
git config user.name "mokogitea-actions[bot]"
|
||||||
|
git remote add origin "https://x-access-token:${TOKEN}@${SERVER#https://}/${REPO}.git"
|
||||||
|
git fetch -q --depth=1 origin main
|
||||||
|
|
||||||
# 0. dev must exist
|
if git ls-remote --exit-code --heads origin dev >/dev/null 2>&1; then
|
||||||
if ! curl -sf -H "$AUTH" "${API}/branches/dev" >/dev/null 2>&1; then
|
# dev exists -> force it to match main (dev is a mirror of main)
|
||||||
echo "No dev branch - nothing to cascade."; exit 0
|
git push --force origin FETCH_HEAD:refs/heads/dev
|
||||||
fi
|
echo "dev reset to main" >> "$GITHUB_STEP_SUMMARY"
|
||||||
|
|
||||||
# 1. is main ahead of dev?
|
|
||||||
AHEAD=$(curl -sf -H "$AUTH" "${API}/compare/dev...main" \
|
|
||||||
| python3 -c "import sys,json; print(json.load(sys.stdin).get('total_commits',0))" 2>/dev/null || echo 0)
|
|
||||||
if [ "${AHEAD:-0}" -eq 0 ]; then
|
|
||||||
echo "dev already up to date with main."; exit 0
|
|
||||||
fi
|
|
||||||
echo "main is ${AHEAD} commit(s) ahead of dev."
|
|
||||||
|
|
||||||
# 2. reuse an open main->dev PR, else create one
|
|
||||||
PR=$(curl -sf -H "$AUTH" "${API}/pulls?state=open&base=dev" \
|
|
||||||
| python3 -c "import sys,json; d=json.load(sys.stdin); print(next((str(p['number']) for p in d if p.get('head',{}).get('ref')=='main'), ''))" 2>/dev/null || echo "")
|
|
||||||
if [ -z "$PR" ]; then
|
|
||||||
RESP=$(curl -s -H "$AUTH" -H "Content-Type: application/json" -X POST "${API}/pulls" \
|
|
||||||
-d '{"head":"main","base":"dev","title":"chore(sync): cascade main -> dev","body":"Automated cascade of main into dev. Auto-merges when conflict-free, auto-resolves VERSION-stamp-only conflicts, otherwise left open for manual resolution."}')
|
|
||||||
PR=$(printf '%s' "$RESP" | jqget number)
|
|
||||||
if [ -z "$PR" ]; then
|
|
||||||
echo "::warning::Could not open cascade PR: $RESP"; exit 0
|
|
||||||
fi
|
|
||||||
echo "Opened cascade PR #${PR}"
|
|
||||||
else
|
else
|
||||||
echo "Reusing open cascade PR #${PR}"
|
# dev missing (e.g. renamed to rc mid-cycle) -> recreate from main
|
||||||
|
git push origin FETCH_HEAD:refs/heads/dev
|
||||||
|
echo "dev created from main" >> "$GITHUB_STEP_SUMMARY"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
notify() {
|
|
||||||
curl -sS \
|
|
||||||
-H "Title: ${REPO}: dev cascade needs manual merge" \
|
|
||||||
-H "Tags: warning,twisted_rightwards_arrows" \
|
|
||||||
-H "Priority: high" \
|
|
||||||
-H "Click: ${MOKOGITEA_URL}/${REPO}/pulls/${PR}" \
|
|
||||||
-d "main -> dev cascade PR #${PR} $1 It was NOT auto-merged; resolve it manually." \
|
|
||||||
"${NTFY_URL}/${NTFY_TOPIC}" || true
|
|
||||||
}
|
|
||||||
|
|
||||||
# 3. wait for MokoGitea to compute mergeability (conflict detection)
|
|
||||||
MERGEABLE=""
|
|
||||||
for _ in 1 2 3 4 5 6; do
|
|
||||||
MERGEABLE=$(curl -sf -H "$AUTH" "${API}/pulls/${PR}" | jqget mergeable)
|
|
||||||
case "$MERGEABLE" in True|False) break ;; esac
|
|
||||||
sleep 3
|
|
||||||
done
|
|
||||||
echo "mergeable=${MERGEABLE}"
|
|
||||||
|
|
||||||
# 4a. conflict-free -> merge via API (existing behaviour)
|
|
||||||
if [ "$MERGEABLE" = "True" ]; then
|
|
||||||
CODE=$(curl -s -o /tmp/merge.json -w "%{http_code}" -H "$AUTH" -H "Content-Type: application/json" \
|
|
||||||
-X POST "${API}/pulls/${PR}/merge" -d '{"Do":"merge","merge_when_checks_succeed":true}')
|
|
||||||
if [ "$CODE" -ge 200 ] && [ "$CODE" -lt 300 ]; then
|
|
||||||
echo "Cascade PR #${PR} merged (or scheduled to merge when checks pass)."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
echo "::warning::Auto-merge returned HTTP ${CODE}: $(cat /tmp/merge.json)"
|
|
||||||
notify "could not be auto-merged (HTTP ${CODE})."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 4b. conflicts -> try to auto-resolve if they are ONLY VERSION-stamp lines.
|
|
||||||
echo "PR not cleanly mergeable; checking whether conflicts are VERSION-stamp-only..."
|
|
||||||
git config user.name "MokoGitea Cascade"
|
|
||||||
git config user.email "actions@mokoconsulting.tech"
|
|
||||||
git fetch --quiet origin main dev
|
|
||||||
git checkout -B dev origin/dev
|
|
||||||
|
|
||||||
if git merge --no-ff --no-commit origin/main >/dev/null 2>&1; then
|
|
||||||
# Became clean at git level (e.g. mergeability was still computing) -> commit + push.
|
|
||||||
git commit -m "chore(sync): cascade main -> dev [skip ci]" >/dev/null
|
|
||||||
git push origin dev
|
|
||||||
echo "Cascade merged cleanly at git level and pushed to dev."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
CONFLICTS=$(git diff --name-only --diff-filter=U)
|
|
||||||
echo "Conflicted files:"; echo "${CONFLICTS}"
|
|
||||||
|
|
||||||
# A conflict is "stamp-only" when every line inside every conflict block matches
|
|
||||||
# a version-stamp pattern (VERSION: header, <version> element, or CHANGELOG title).
|
|
||||||
is_stamp_only() {
|
|
||||||
awk '
|
|
||||||
/^<<<<<<< / { inc=1; next }
|
|
||||||
inc && /^=======$/ { next }
|
|
||||||
/^>>>>>>> / { inc=0; next }
|
|
||||||
inc { if ($0 !~ /(VERSION:|<version>|# Changelog)/) { bad=1 } }
|
|
||||||
END { exit(bad ? 1 : 0) }
|
|
||||||
' "$1"
|
|
||||||
}
|
|
||||||
# Resolve a stamp-only file by keeping dev (ours) for the conflicting lines,
|
|
||||||
# preserving all auto-merged content around them.
|
|
||||||
keep_ours() {
|
|
||||||
awk '
|
|
||||||
/^<<<<<<< / { inc=1; side="ours"; next }
|
|
||||||
inc && /^=======$/ { side="theirs"; next }
|
|
||||||
/^>>>>>>> / { inc=0; next }
|
|
||||||
{ if (!inc) { print; next } if (side=="ours") print }
|
|
||||||
' "$1" > "$1.resolved" && mv "$1.resolved" "$1"
|
|
||||||
}
|
|
||||||
|
|
||||||
ALL_STAMP=1
|
|
||||||
for f in ${CONFLICTS}; do
|
|
||||||
if ! is_stamp_only "$f"; then
|
|
||||||
echo "::notice::$f has non-stamp conflicts -> manual resolution required."
|
|
||||||
ALL_STAMP=0; break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ "$ALL_STAMP" != "1" ]; then
|
|
||||||
git merge --abort || true
|
|
||||||
notify "has non-version-stamp conflicts and cannot be auto-resolved."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "All conflicts are VERSION-stamp-only; resolving in favour of dev."
|
|
||||||
for f in ${CONFLICTS}; do
|
|
||||||
keep_ours "$f"
|
|
||||||
git add "$f"
|
|
||||||
done
|
|
||||||
|
|
||||||
# Best-effort: normalise stamps to dev's version if mokocli is available.
|
|
||||||
if [ -f /opt/mokocli/cli/version_check.php ]; then
|
|
||||||
php /opt/mokocli/cli/version_check.php --fix || true
|
|
||||||
git add -A
|
|
||||||
fi
|
|
||||||
|
|
||||||
git commit -m "chore(sync): cascade main -> dev (auto-resolved version stamps) [skip ci]" >/dev/null
|
|
||||||
git push origin dev
|
|
||||||
echo "Cascade auto-resolved and pushed to dev."
|
|
||||||
|
|
||||||
# Close the now-redundant PR (its changes are in dev) with an explanatory comment.
|
|
||||||
curl -s -H "$AUTH" -H "Content-Type: application/json" -X POST "${API}/issues/${PR}/comments" \
|
|
||||||
-d '{"body":"Auto-resolved VERSION-stamp-only conflicts and pushed the merge to dev. Closing."}' >/dev/null || true
|
|
||||||
curl -s -H "$AUTH" -H "Content-Type: application/json" -X PATCH "${API}/pulls/${PR}" \
|
|
||||||
-d '{"state":"closed"}' >/dev/null || true
|
|
||||||
|
|||||||
@@ -131,11 +131,10 @@ jobs:
|
|||||||
test:
|
test:
|
||||||
name: Tests
|
name: Tests
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
# Independent job (no `needs: lint`): the MokoGitea Actions scheduler does not
|
needs: lint
|
||||||
# offer the dependent 2nd job of a needs-chain to runners, so it stalls in
|
# Run only when lint succeeded; always() forces evaluation so a skipped
|
||||||
# "waiting" and is reaped by ABANDONED_JOB_TIMEOUT. Guard template repos
|
# lint (e.g. template repos) skips this job cleanly instead of hanging.
|
||||||
# directly (same condition lint uses) instead of gating on lint's result.
|
if: ${{ always() && needs.lint.result == 'success' }}
|
||||||
if: ${{ !startsWith(github.event.repository.name, 'Template-') }}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
# FILE INFORMATION
|
# FILE INFORMATION
|
||||||
# DEFGROUP: MokoGitea.Workflow
|
# DEFGROUP: MokoGitea.Workflow
|
||||||
# INGROUP: MokoCLI.Universal
|
# INGROUP: MokoCLI.Universal
|
||||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
|
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||||
# PATH: /.mokogitea/workflows/ci-issue-reporter.yml
|
# PATH: /.mokogitea/workflows/ci-issue-reporter.yml
|
||||||
# VERSION: 01.00.00
|
# VERSION: 01.00.00
|
||||||
# BRIEF: Reusable workflow — creates/updates a MokoGitea issue when a CI gate fails.
|
# BRIEF: Reusable workflow — creates/updates a MokoGitea issue when a CI gate fails.
|
||||||
|
|||||||
+1328
-33
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@
|
|||||||
# DEFGROUP: MokoGitea.Workflow
|
# DEFGROUP: MokoGitea.Workflow
|
||||||
# INGROUP: MokoCLI.Security
|
# INGROUP: MokoCLI.Security
|
||||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||||
# PATH: /.mokogitea/workflows/gitleaks.yml
|
# PATH: /templates/workflows/gitleaks.yml.template
|
||||||
# VERSION: 01.00.00
|
# VERSION: 01.00.00
|
||||||
# BRIEF: Secret scanning — detect leaked credentials, API keys, and tokens
|
# BRIEF: Secret scanning — detect leaked credentials, API keys, and tokens
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
# FILE INFORMATION
|
# FILE INFORMATION
|
||||||
# DEFGROUP: MokoGitea.Workflow
|
# DEFGROUP: MokoGitea.Workflow
|
||||||
# INGROUP: MokoCLI.Automation
|
# INGROUP: MokoCLI.Automation
|
||||||
# VERSION: 02.63.03
|
# VERSION: 01.00.00
|
||||||
# BRIEF: Auto-create feature branch when an issue is opened
|
# BRIEF: Auto-create feature branch when an issue is opened
|
||||||
|
|
||||||
name: "Universal: Issue Branch"
|
name: "Universal: Issue Branch"
|
||||||
|
|||||||
@@ -46,13 +46,13 @@ jobs:
|
|||||||
WORKFLOW="${{ github.event.workflow_run.name }}"
|
WORKFLOW="${{ github.event.workflow_run.name }}"
|
||||||
URL="${{ github.event.workflow_run.html_url }}"
|
URL="${{ github.event.workflow_run.html_url }}"
|
||||||
|
|
||||||
curl -sS --retry 3 --retry-connrefused --retry-delay 2 --max-time 20 \
|
curl -sS \
|
||||||
-H "Title: ${REPO} released" \
|
-H "Title: ${REPO} released" \
|
||||||
-H "Tags: white_check_mark,package" \
|
-H "Tags: white_check_mark,package" \
|
||||||
-H "Priority: default" \
|
-H "Priority: default" \
|
||||||
-H "Click: ${URL}" \
|
-H "Click: ${URL}" \
|
||||||
-d "${WORKFLOW} completed successfully." \
|
-d "${WORKFLOW} completed successfully." \
|
||||||
"${NTFY_URL}/${NTFY_TOPIC}" || echo "::warning::ntfy notification could not be delivered (non-fatal)"
|
"${NTFY_URL}/${NTFY_TOPIC}"
|
||||||
|
|
||||||
- name: Notify on failure
|
- name: Notify on failure
|
||||||
if: github.event.workflow_run.conclusion == 'failure'
|
if: github.event.workflow_run.conclusion == 'failure'
|
||||||
@@ -61,10 +61,10 @@ jobs:
|
|||||||
WORKFLOW="${{ github.event.workflow_run.name }}"
|
WORKFLOW="${{ github.event.workflow_run.name }}"
|
||||||
URL="${{ github.event.workflow_run.html_url }}"
|
URL="${{ github.event.workflow_run.html_url }}"
|
||||||
|
|
||||||
curl -sS --retry 3 --retry-connrefused --retry-delay 2 --max-time 20 \
|
curl -sS \
|
||||||
-H "Title: ${REPO} workflow failed" \
|
-H "Title: ${REPO} workflow failed" \
|
||||||
-H "Tags: x,warning" \
|
-H "Tags: x,warning" \
|
||||||
-H "Priority: high" \
|
-H "Priority: high" \
|
||||||
-H "Click: ${URL}" \
|
-H "Click: ${URL}" \
|
||||||
-d "${WORKFLOW} failed. Check the run for details." \
|
-d "${WORKFLOW} failed. Check the run for details." \
|
||||||
"${NTFY_URL}/${NTFY_TOPIC}" || echo "::warning::ntfy notification could not be delivered (non-fatal)"
|
"${NTFY_URL}/${NTFY_TOPIC}"
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
# FILE INFORMATION
|
# FILE INFORMATION
|
||||||
# DEFGROUP: MokoGitea.Workflow
|
# DEFGROUP: MokoGitea.Workflow
|
||||||
# INGROUP: MokoCLI.CI
|
# INGROUP: MokoCLI.CI
|
||||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
|
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||||
# PATH: /.mokogitea/workflows/pr-check.yml
|
# PATH: /templates/workflows/universal/pr-check.yml.template
|
||||||
# VERSION: 09.23.00
|
# VERSION: 09.23.00
|
||||||
# BRIEF: PR gate — branch policy + code validation before merge
|
# BRIEF: PR gate — branch policy + code validation before merge
|
||||||
|
|
||||||
@@ -47,15 +47,15 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
fix/*|bugfix/*)
|
fix/*|bugfix/*)
|
||||||
if [ "$BASE" != "dev" ] && [ "$BASE" != "main" ]; then
|
if [ "$BASE" != "dev" ]; then
|
||||||
ALLOWED=false
|
ALLOWED=false
|
||||||
REASON="Fix branches must target 'dev' or 'main', not '${BASE}'"
|
REASON="Fix branches must target 'dev', not '${BASE}'"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
patch/*)
|
patch/*)
|
||||||
if [ "$BASE" != "dev" ] && [ "$BASE" != "rc" ] && [ "$BASE" != "main" ]; then
|
if [ "$BASE" != "dev" ] && [ "$BASE" != "rc" ]; then
|
||||||
ALLOWED=false
|
ALLOWED=false
|
||||||
REASON="Patch branches must target 'dev', 'rc', or 'main', not '${BASE}'"
|
REASON="Patch branches must target 'dev' or 'rc', not '${BASE}'"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
hotfix/*)
|
hotfix/*)
|
||||||
@@ -86,8 +86,7 @@ jobs:
|
|||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "### Allowed merge paths:" >> $GITHUB_STEP_SUMMARY
|
echo "### Allowed merge paths:" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "- \`feature/*\` → \`dev\`" >> $GITHUB_STEP_SUMMARY
|
echo "- \`feature/*\` → \`dev\`" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "- \`fix/*\` → \`dev\` or \`main\`" >> $GITHUB_STEP_SUMMARY
|
echo "- \`fix/*\` → \`dev\`" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "- \`patch/*\` → \`dev\`, \`rc\`, or \`main\`" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "- \`hotfix/*\` → \`dev\` or \`main\`" >> $GITHUB_STEP_SUMMARY
|
echo "- \`hotfix/*\` → \`dev\` or \`main\`" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "- \`dev\` → \`main\`" >> $GITHUB_STEP_SUMMARY
|
echo "- \`dev\` → \`main\`" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "- \`rc/*\` → \`main\`" >> $GITHUB_STEP_SUMMARY
|
echo "- \`rc/*\` → \`main\`" >> $GITHUB_STEP_SUMMARY
|
||||||
@@ -97,80 +96,6 @@ jobs:
|
|||||||
echo "Branch policy: OK (${HEAD} → ${BASE})"
|
echo "Branch policy: OK (${HEAD} → ${BASE})"
|
||||||
echo "## Branch Policy: Passed" >> $GITHUB_STEP_SUMMARY
|
echo "## Branch Policy: Passed" >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
# ── Docs Update Gate (main PRs) ─────────────────────────────────────────
|
|
||||||
require-docs:
|
|
||||||
name: Require Docs Update
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
# Enforce only on PRs merging into main: README.md + CHANGELOG.md must both be updated.
|
|
||||||
if: ${{ github.base_ref == 'main' }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Require README.md and CHANGELOG.md in the PR diff
|
|
||||||
run: |
|
|
||||||
BASE="${{ github.event.pull_request.base.sha }}"
|
|
||||||
HEAD="${{ github.event.pull_request.head.sha }}"
|
|
||||||
CHANGED="$(git diff --name-only "$BASE" "$HEAD" 2>/dev/null || true)"
|
|
||||||
if [ -z "$CHANGED" ]; then
|
|
||||||
git fetch -q origin "${{ github.base_ref }}" 2>/dev/null || true
|
|
||||||
CHANGED="$(git diff --name-only "origin/${{ github.base_ref }}...HEAD" 2>/dev/null || true)"
|
|
||||||
fi
|
|
||||||
echo "Changed files in PR:"
|
|
||||||
echo "$CHANGED"
|
|
||||||
MISSING=""
|
|
||||||
echo "$CHANGED" | grep -qxE 'README\.md' || MISSING="README.md"
|
|
||||||
echo "$CHANGED" | grep -qxE 'CHANGELOG\.md' || MISSING="${MISSING:+$MISSING, }CHANGELOG.md"
|
|
||||||
if [ -n "$MISSING" ]; then
|
|
||||||
echo "::error::PRs into main must update: ${MISSING}"
|
|
||||||
{
|
|
||||||
echo "## Docs Update Required"
|
|
||||||
echo ""
|
|
||||||
echo "PRs merging into \`main\` must update both **README.md** and **CHANGELOG.md**."
|
|
||||||
echo ""
|
|
||||||
echo "Not updated in this PR: **${MISSING}**"
|
|
||||||
} >> "$GITHUB_STEP_SUMMARY"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo "Docs update present (README.md + CHANGELOG.md)"
|
|
||||||
echo "## Docs Update: Passed" >> "$GITHUB_STEP_SUMMARY"
|
|
||||||
|
|
||||||
# ── Wiki Update Reminder (main PRs, non-blocking) ───────────────────────
|
|
||||||
wiki-reminder:
|
|
||||||
name: Wiki Update Reminder
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: ${{ github.base_ref == 'main' }}
|
|
||||||
steps:
|
|
||||||
- name: Remind to update the wiki
|
|
||||||
env:
|
|
||||||
TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
|
||||||
SERVER: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
|
||||||
REPO: ${{ github.repository }}
|
|
||||||
PR: ${{ github.event.pull_request.number }}
|
|
||||||
run: |
|
|
||||||
set -uo pipefail
|
|
||||||
{
|
|
||||||
echo "## Wiki Update Reminder"
|
|
||||||
echo ""
|
|
||||||
echo "Docs are **wiki-first** at MokoConsulting. If this change affects behavior, usage, configuration, or standards, update the repo wiki:"
|
|
||||||
echo ""
|
|
||||||
echo "- ${SERVER}/${REPO}/wiki"
|
|
||||||
echo ""
|
|
||||||
echo "_Non-blocking reminder._"
|
|
||||||
} >> "$GITHUB_STEP_SUMMARY"
|
|
||||||
# Post a single PR comment (idempotent via hidden marker); best-effort, never fails.
|
|
||||||
API="${SERVER}/api/v1/repos/${REPO}/issues/${PR}/comments"
|
|
||||||
if [ -n "${TOKEN:-}" ] && [ -n "${PR:-}" ]; then
|
|
||||||
existing="$(curl -sf -H "Authorization: token ${TOKEN}" "$API" 2>/dev/null | grep -c 'wiki-reminder' || true)"
|
|
||||||
if [ "${existing:-0}" -eq 0 ]; then
|
|
||||||
curl -sf -H "Authorization: token ${TOKEN}" -H "Content-Type: application/json" -X POST "$API" \
|
|
||||||
-d '{"body":"<!-- wiki-reminder -->\n\n**Wiki reminder:** docs are wiki-first -- if this PR changes behavior, usage, config, or standards, please update the repo wiki before/after merge. _(non-blocking)_"}' >/dev/null 2>&1 || true
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
echo "Wiki reminder emitted (non-blocking)."
|
|
||||||
|
|
||||||
# ── Secret Scanning ──────────────────────────────────────────────────
|
# ── Secret Scanning ──────────────────────────────────────────────────
|
||||||
gitleaks:
|
gitleaks:
|
||||||
name: Secret Scan
|
name: Secret Scan
|
||||||
@@ -210,7 +135,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Check for merge conflict markers
|
- name: Check for merge conflict markers
|
||||||
run: |
|
run: |
|
||||||
CONFLICTS=$(grep -rn '<<<<<<< \|>>>>>>> \|^=======$' --exclude-dir='.git' --exclude-dir='.mokogitea' --include='*.php' --include='*.xml' --include='*.css' --include='*.js' --include='*.json' --include='*.md' --include='*.yml' --include='*.yaml' --include='*.ini' --include='*.txt' . 2>/dev/null | grep -v '.git/' || true)
|
CONFLICTS=$(grep -rn '<<<<<<< \|>>>>>>> \|^=======$' --include='*.php' --include='*.xml' --include='*.css' --include='*.js' --include='*.json' --include='*.md' --include='*.yml' --include='*.yaml' --include='*.ini' --include='*.txt' . 2>/dev/null | grep -v '.git/' || true)
|
||||||
if [ -n "$CONFLICTS" ]; then
|
if [ -n "$CONFLICTS" ]; then
|
||||||
echo "::error::Merge conflict markers found in source files"
|
echo "::error::Merge conflict markers found in source files"
|
||||||
echo "## Conflict Markers Found" >> $GITHUB_STEP_SUMMARY
|
echo "## Conflict Markers Found" >> $GITHUB_STEP_SUMMARY
|
||||||
@@ -224,7 +149,7 @@ jobs:
|
|||||||
- name: Detect platform
|
- name: Detect platform
|
||||||
id: platform
|
id: platform
|
||||||
run: |
|
run: |
|
||||||
# Platform comes from the MokoGitea metadata API (public GET).
|
# Platform comes from the MokoGitea metadata API (public GET); manifest.xml is no longer used.
|
||||||
API="${GITHUB_SERVER_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${GITHUB_REPOSITORY}/metadata"
|
API="${GITHUB_SERVER_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${GITHUB_REPOSITORY}/metadata"
|
||||||
PLATFORM="$(curl -sf "$API" 2>/dev/null | python3 -c "import sys, json; print(json.load(sys.stdin).get('platform') or '')" 2>/dev/null || true)"
|
PLATFORM="$(curl -sf "$API" 2>/dev/null | python3 -c "import sys, json; print(json.load(sys.stdin).get('platform') or '')" 2>/dev/null || true)"
|
||||||
[ -z "$PLATFORM" ] && PLATFORM="generic"
|
[ -z "$PLATFORM" ] && PLATFORM="generic"
|
||||||
@@ -258,9 +183,8 @@ jobs:
|
|||||||
while IFS= read -r -d '' file; do
|
while IFS= read -r -d '' file; do
|
||||||
# Skip vendor, node_modules, and index.html stub files
|
# Skip vendor, node_modules, and index.html stub files
|
||||||
case "$file" in ./vendor/*|./node_modules/*) continue ;; esac
|
case "$file" in ./vendor/*|./node_modules/*) continue ;; esac
|
||||||
# Scan the whole file for the JEXEC/JPATH guard: it is placed after
|
# Check first 10 lines for JEXEC or JPATH guard
|
||||||
# the SPDX/file-header docblock, which commonly runs past 20 lines.
|
if ! head -20 "$file" | grep -qE "defined\s*\(\s*['\"](_JEXEC|JPATH_BASE|\\\\JPATH_PLATFORM)['\"]"; then
|
||||||
if ! grep -qE "defined\s*\(\s*['\"](_JEXEC|JPATH_BASE|\\\\JPATH_PLATFORM)['\"]" "$file"; then
|
|
||||||
echo "::error file=${file}::Missing JEXEC guard: ${file}"
|
echo "::error file=${file}::Missing JEXEC guard: ${file}"
|
||||||
ERRORS=$((ERRORS + 1))
|
ERRORS=$((ERRORS + 1))
|
||||||
fi
|
fi
|
||||||
@@ -351,7 +275,7 @@ jobs:
|
|||||||
joomla)
|
joomla)
|
||||||
MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
|
MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
|
||||||
if [ -z "$MANIFEST" ]; then
|
if [ -z "$MANIFEST" ]; then
|
||||||
echo "::warning::No Joomla manifest found (MokoSuite site)"
|
echo "::warning::No Joomla manifest found (WaaS site)"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
echo "Manifest: ${MANIFEST}"
|
echo "Manifest: ${MANIFEST}"
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
#
|
#
|
||||||
# FILE INFORMATION
|
# FILE INFORMATION
|
||||||
# DEFGROUP: Gitea.Workflow
|
# DEFGROUP: MokoGitea.Workflow
|
||||||
# INGROUP: mokocli.Validation
|
# INGROUP: MokoCLI.Validation
|
||||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||||
# PATH: /templates/workflows/joomla/pr-metadata-check.yml.template
|
# PATH: /templates/workflows/joomla/pr-metadata-check.yml.template
|
||||||
# VERSION: 01.00.00
|
# VERSION: 01.00.00
|
||||||
@@ -20,7 +20,7 @@ permissions:
|
|||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
env:
|
env:
|
||||||
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||||
GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }}
|
GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }}
|
||||||
GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }}
|
GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }}
|
||||||
|
|
||||||
@@ -28,12 +28,14 @@ jobs:
|
|||||||
validate-metadata:
|
validate-metadata:
|
||||||
name: "Validate Joomla Metadata"
|
name: "Validate Joomla Metadata"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
# Skip on template repos (Template-*) — they have no real extension manifest to validate.
|
||||||
|
if: ${{ !startsWith(github.event.repository.name, 'Template-') }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup mokocli tools
|
- name: Setup MokoCLI tools
|
||||||
env:
|
env:
|
||||||
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||||
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
||||||
@@ -55,14 +57,14 @@ jobs:
|
|||||||
|
|
||||||
- name: Validate metadata against Joomla manifest
|
- name: Validate metadata against Joomla manifest
|
||||||
env:
|
env:
|
||||||
GITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
php ${MOKO_CLI}/joomla_metadata_validate.php \
|
php ${MOKO_CLI}/joomla_metadata_validate.php \
|
||||||
--path . \
|
--path . \
|
||||||
--token "${GITEA_TOKEN}" \
|
--token "${MOKOGITEA_TOKEN}" \
|
||||||
--org "${GITEA_ORG}" \
|
--org "${GITEA_ORG}" \
|
||||||
--repo "${GITEA_REPO}" \
|
--repo "${GITEA_REPO}" \
|
||||||
--api-base "${GITEA_URL}/api/v1" \
|
--api-base "${MOKOGITEA_URL}/api/v1" \
|
||||||
--ci
|
--ci
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
# FILE INFORMATION
|
# FILE INFORMATION
|
||||||
# DEFGROUP: MokoGitea.Workflow
|
# DEFGROUP: MokoGitea.Workflow
|
||||||
# INGROUP: MokoCLI.Release
|
# INGROUP: MokoCLI.Release
|
||||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
|
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||||
# PATH: /.mokogitea/workflows/pre-release.yml
|
# PATH: /templates/workflows/universal/pre-release.yml.template
|
||||||
# VERSION: 05.02.01
|
# VERSION: 05.02.00
|
||||||
# BRIEF: Auto pre-release on push to dev/alpha/beta/rc branches
|
# BRIEF: Auto pre-release on push to dev/alpha/beta/rc branches
|
||||||
|
|
||||||
name: "Universal: Pre-Release"
|
name: "Universal: Pre-Release"
|
||||||
@@ -162,13 +162,7 @@ jobs:
|
|||||||
git add -A
|
git add -A
|
||||||
git diff --cached --quiet || {
|
git diff --cached --quiet || {
|
||||||
git commit -m "chore(version): pre-release bump to ${VERSION} [skip ci]"
|
git commit -m "chore(version): pre-release bump to ${VERSION} [skip ci]"
|
||||||
# Push the bump commit, but do NOT fail the release if the target branch
|
git push origin HEAD 2>&1
|
||||||
# is protected and the release identity is not on the push allowlist.
|
|
||||||
# The build proceeds from the in-tree bumped version regardless; if the
|
|
||||||
# push is rejected, the next run simply re-bumps from the same base.
|
|
||||||
if ! git push origin HEAD 2>&1; then
|
|
||||||
echo "::warning::Version-bump commit could not be pushed (protected branch?). Building from in-tree version ${VERSION} anyway."
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Auto-detect element via manifest_element.php
|
# Auto-detect element via manifest_element.php
|
||||||
@@ -280,4 +274,4 @@ jobs:
|
|||||||
echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
|
echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "| Channel | ${STABILITY} |" >> $GITHUB_STEP_SUMMARY
|
echo "| Channel | ${STABILITY} |" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "| Package | \`${ZIP_NAME}\` |" >> $GITHUB_STEP_SUMMARY
|
echo "| Package | \`${ZIP_NAME}\` |" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "| SHA-256 | \`${SHA256:-n/a}\` |" >> $GITHUB_STEP_SUMMARY
|
echo "| SHA-256 | \`${SHA256:-n/a}\` |" >> $GITHUB_STEP_SUMMARY
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
# FILE INFORMATION
|
# FILE INFORMATION
|
||||||
# DEFGROUP: MokoGitea.Workflow
|
# DEFGROUP: MokoGitea.Workflow
|
||||||
# INGROUP: MokoCLI.Universal
|
# INGROUP: MokoCLI.Universal
|
||||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
|
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||||
# PATH: /.mokogitea/workflows/rc-revert.yml
|
# PATH: /.mokogitea/workflows/rc-revert.yml
|
||||||
# VERSION: 09.23.00
|
# VERSION: 09.23.00
|
||||||
# BRIEF: Rename rc/ branch back to dev/ when PR is closed without merge
|
# BRIEF: Rename rc/ branch back to dev/ when PR is closed without merge
|
||||||
@@ -25,8 +25,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: >-
|
if: >-
|
||||||
github.event.pull_request.merged == false &&
|
github.event.pull_request.merged == false &&
|
||||||
startsWith(github.event.pull_request.head.ref, 'rc/') &&
|
startsWith(github.event.pull_request.head.ref, 'rc/')
|
||||||
!startsWith(github.event.repository.name, 'Template-')
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Rename branch
|
- name: Rename branch
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
# FILE INFORMATION
|
# FILE INFORMATION
|
||||||
# DEFGROUP: MokoGitea.Workflow
|
# DEFGROUP: MokoGitea.Workflow
|
||||||
# INGROUP: MokoCLI.Validation
|
# INGROUP: MokoCLI.Validation
|
||||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
|
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||||
# PATH: /.mokogitea/workflows/repo-health.yml
|
# PATH: /templates/workflows/joomla/repo_health.yml.template
|
||||||
# VERSION: 09.23.00
|
# VERSION: 09.23.00
|
||||||
# BRIEF: Enforces repository guardrails by validating scripts governance, tooling availability, and core repository health artifacts.
|
# BRIEF: Enforces repository guardrails by validating scripts governance, tooling availability, and core repository health artifacts.
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ jobs:
|
|||||||
set-version:
|
set-version:
|
||||||
name: Set Version to ${{ inputs.version }}
|
name: Set Version to ${{ inputs.version }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ !startsWith(github.event.repository.name, 'Template-') }}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Validate version format
|
- name: Validate version format
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ DEFGROUP: Template-Joomla
|
|||||||
INGROUP: Template-Joomla.Documentation
|
INGROUP: Template-Joomla.Documentation
|
||||||
REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Joomla
|
REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Joomla
|
||||||
PATH: /SECURITY.md
|
PATH: /SECURITY.md
|
||||||
VERSION: 02.63.03
|
VERSION: 02.63.00
|
||||||
BRIEF: Security vulnerability reporting and handling policy
|
BRIEF: Security vulnerability reporting and handling policy
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
|||||||
Submodule source/packages/MokoSuiteClient updated: 45f24efa16...81b2453e75
@@ -17,7 +17,7 @@
|
|||||||
display label there.
|
display label there.
|
||||||
-->
|
-->
|
||||||
<name>MokoSuiteBackup</name>
|
<name>MokoSuiteBackup</name>
|
||||||
<version>02.63.03</version>
|
<version>02.63.00</version>
|
||||||
<creationDate>2026-06-02</creationDate>
|
<creationDate>2026-06-02</creationDate>
|
||||||
<author>Moko Consulting</author>
|
<author>Moko Consulting</author>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
/* 02.63.03 — no schema changes */
|
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
-->
|
-->
|
||||||
<extension type="module" client="administrator" method="upgrade">
|
<extension type="module" client="administrator" method="upgrade">
|
||||||
<name>Module - MokoSuiteBackup - cPanel</name>
|
<name>Module - MokoSuiteBackup - cPanel</name>
|
||||||
<version>02.63.03</version>
|
<version>02.63.00</version>
|
||||||
<creationDate>2026-06-23</creationDate>
|
<creationDate>2026-06-23</creationDate>
|
||||||
<author>Moko Consulting</author>
|
<author>Moko Consulting</author>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
-->
|
-->
|
||||||
<extension type="plugin" group="actionlog" method="upgrade">
|
<extension type="plugin" group="actionlog" method="upgrade">
|
||||||
<name>Action Log - MokoSuiteBackup</name>
|
<name>Action Log - MokoSuiteBackup</name>
|
||||||
<version>02.63.03</version>
|
<version>02.63.00</version>
|
||||||
<creationDate>2026-06-04</creationDate>
|
<creationDate>2026-06-04</creationDate>
|
||||||
<author>Moko Consulting</author>
|
<author>Moko Consulting</author>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
-->
|
-->
|
||||||
<extension type="plugin" group="console" method="upgrade">
|
<extension type="plugin" group="console" method="upgrade">
|
||||||
<name>Console - MokoSuiteBackup</name>
|
<name>Console - MokoSuiteBackup</name>
|
||||||
<version>02.63.03</version>
|
<version>02.63.00</version>
|
||||||
<creationDate>2026-06-04</creationDate>
|
<creationDate>2026-06-04</creationDate>
|
||||||
<author>Moko Consulting</author>
|
<author>Moko Consulting</author>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
-->
|
-->
|
||||||
<extension type="plugin" group="content" method="upgrade">
|
<extension type="plugin" group="content" method="upgrade">
|
||||||
<name>Content - MokoSuiteBackup</name>
|
<name>Content - MokoSuiteBackup</name>
|
||||||
<version>02.63.03</version>
|
<version>02.63.00</version>
|
||||||
<creationDate>2026-06-04</creationDate>
|
<creationDate>2026-06-04</creationDate>
|
||||||
<author>Moko Consulting</author>
|
<author>Moko Consulting</author>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<extension type="plugin" group="quickicon" method="upgrade">
|
<extension type="plugin" group="quickicon" method="upgrade">
|
||||||
<name>Quick Icon - MokoSuiteBackup</name>
|
<name>Quick Icon - MokoSuiteBackup</name>
|
||||||
<version>02.63.03</version>
|
<version>02.63.00</version>
|
||||||
<creationDate>2026-06-02</creationDate>
|
<creationDate>2026-06-02</creationDate>
|
||||||
<author>Moko Consulting</author>
|
<author>Moko Consulting</author>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
-->
|
-->
|
||||||
<extension type="plugin" group="system" method="upgrade">
|
<extension type="plugin" group="system" method="upgrade">
|
||||||
<name>System - MokoSuiteBackup</name>
|
<name>System - MokoSuiteBackup</name>
|
||||||
<version>02.63.03</version>
|
<version>02.63.00</version>
|
||||||
<creationDate>2026-06-02</creationDate>
|
<creationDate>2026-06-02</creationDate>
|
||||||
<author>Moko Consulting</author>
|
<author>Moko Consulting</author>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
-->
|
-->
|
||||||
<extension type="plugin" group="task" method="upgrade">
|
<extension type="plugin" group="task" method="upgrade">
|
||||||
<name>Task - MokoSuiteBackup</name>
|
<name>Task - MokoSuiteBackup</name>
|
||||||
<version>02.63.03</version>
|
<version>02.63.00</version>
|
||||||
<creationDate>2026-06-02</creationDate>
|
<creationDate>2026-06-02</creationDate>
|
||||||
<author>Moko Consulting</author>
|
<author>Moko Consulting</author>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
-->
|
-->
|
||||||
<extension type="plugin" group="webservices" method="upgrade">
|
<extension type="plugin" group="webservices" method="upgrade">
|
||||||
<name>Web Services - MokoSuiteBackup</name>
|
<name>Web Services - MokoSuiteBackup</name>
|
||||||
<version>02.63.03</version>
|
<version>02.63.00</version>
|
||||||
<creationDate>2026-06-02</creationDate>
|
<creationDate>2026-06-02</creationDate>
|
||||||
<author>Moko Consulting</author>
|
<author>Moko Consulting</author>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<extension type="package" method="upgrade">
|
<extension type="package" method="upgrade">
|
||||||
<name>Package - MokoSuiteBackup</name>
|
<name>Package - MokoSuiteBackup</name>
|
||||||
<packagename>mokosuitebackup</packagename>
|
<packagename>mokosuitebackup</packagename>
|
||||||
<version>02.63.03</version>
|
<version>02.63.00</version>
|
||||||
<creationDate>2026-06-02</creationDate>
|
<creationDate>2026-06-02</creationDate>
|
||||||
<author>Moko Consulting</author>
|
<author>Moko Consulting</author>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
|
|||||||
Reference in New Issue
Block a user