Public Access
Merge pull request 'chore(rebrand): gitea -> git (MokoGitea -> MokoGit, .mokogitea -> .mokogit)' (#346) from chore/rebrand-gitea-to-git into main
This commit was merged in pull request #346.
This commit is contained in:
@@ -38,7 +38,7 @@ composer check # Run all checks
|
||||
| `lib/Enterprise/Plugins/` | 11 platform plugins (Joomla, Dolibarr, Node.js, Python, etc.) |
|
||||
| `deploy/` | SFTP deployment scripts (Joomla, Dolibarr, health checks) |
|
||||
| `templates/` | Universal templates, configs, governance schema |
|
||||
| `.mokogitea/workflows/` | CI/CD workflows (MokoGitea Actions) |
|
||||
| `.mokogit/workflows/` | CI/CD workflows (MokoGit Actions) |
|
||||
| `bin/moko` | Unified CLI dispatcher — `php bin/moko <command>` |
|
||||
| `monitoring/sites.json` | Sites list for mcp_mokomonitor |
|
||||
|
||||
@@ -50,7 +50,7 @@ After adding a CLI tool, register it in `bin/moko` COMMAND_MAP.
|
||||
|
||||
### Platform Adapters
|
||||
|
||||
- `MokoGiteaAdapter` — git.mokoconsulting.tech (primary)
|
||||
- `MokoGitAdapter` — git.mokoconsulting.tech (primary)
|
||||
- `GitHubAdapter` — github.com mirrors
|
||||
|
||||
### Plugin System
|
||||
@@ -70,7 +70,7 @@ PHPStan runs with `--memory-limit=512M`. CI enforces PHPCS errors; PHPStan is `c
|
||||
|
||||
- **Never commit** `.claude/`, `.mcp.json`, `TODO.md`, `*.min.css`/`*.min.js`
|
||||
- **Attribution**: `Authored-by: Moko Consulting`
|
||||
- **Workflow directory**: `.mokogitea/` (not `.gitea/` or `.github/`)
|
||||
- **Wiki**: documentation lives in the MokoGitea wiki, not `docs/` files
|
||||
- **Workflow directory**: `.mokogit/` (not `.gitea/` or `.github/`)
|
||||
- **Wiki**: documentation lives in the MokoGit wiki, not `docs/` files
|
||||
- **New CLI tools**: extend `CliFramework`, not `CLIApp` (legacy)
|
||||
- **Standards**: [MokoCli](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki/Home)
|
||||
@@ -1,7 +1,7 @@
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# DEFGROUP: Git.Workflow
|
||||
# INGROUP: mokocli.Automation
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
# PATH: /.gitea/workflows/branch-protection.yml
|
||||
@@ -42,8 +42,8 @@ on:
|
||||
default: ''
|
||||
|
||||
env:
|
||||
GITEA_URL: https://git.mokoconsulting.tech
|
||||
GITEA_ORG: MokoConsulting
|
||||
GIT_URL: https://git.mokoconsulting.tech
|
||||
GIT_ORG: MokoConsulting
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -57,12 +57,12 @@ jobs:
|
||||
- name: Determine target repos
|
||||
id: repos
|
||||
env:
|
||||
GA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
GA_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
run: |
|
||||
API="${GITEA_URL}/api/v1"
|
||||
API="${GIT_URL}/api/v1"
|
||||
|
||||
# Platform/standards/infra repos to exclude
|
||||
EXCLUDE="gitea-org-config org-profile gitea-private .mokogitea-private mokocli MokoTesting"
|
||||
EXCLUDE="git-org-config org-profile git-private .mokogit-private mokocli MokoTesting"
|
||||
EXCLUDE="$EXCLUDE MokoCli-Template-Client MokoCli-Template-Dolibarr MokoCli-Template-Generic MokoCli-Template-Joomla MokoDoliProjTemplate"
|
||||
|
||||
if [ -n "${{ inputs.repos }}" ]; then
|
||||
@@ -75,7 +75,7 @@ jobs:
|
||||
while true; do
|
||||
BATCH=$(curl -sS \
|
||||
-H "Authorization: token ${GA_TOKEN}" \
|
||||
"${API}/orgs/${GITEA_ORG}/repos?page=${PAGE}&limit=50" \
|
||||
"${API}/orgs/${GIT_ORG}/repos?page=${PAGE}&limit=50" \
|
||||
| jq -r '.[].name // empty')
|
||||
[ -z "$BATCH" ] && break
|
||||
REPOS="$REPOS $BATCH"
|
||||
@@ -105,10 +105,10 @@ jobs:
|
||||
|
||||
- name: Apply protection rules
|
||||
env:
|
||||
GA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
GA_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
DRY_RUN: ${{ inputs.dry_run || 'false' }}
|
||||
run: |
|
||||
API="${GITEA_URL}/api/v1"
|
||||
API="${GIT_URL}/api/v1"
|
||||
REPOS="${{ steps.repos.outputs.repos }}"
|
||||
|
||||
SUCCESS=0
|
||||
@@ -222,7 +222,7 @@ jobs:
|
||||
curl -sS -o /dev/null -w "" \
|
||||
-X DELETE \
|
||||
-H "Authorization: token ${GA_TOKEN}" \
|
||||
"${API}/repos/${GITEA_ORG}/${REPO}/branch_protections/${ENCODED_NAME}" 2>/dev/null || true
|
||||
"${API}/repos/${GIT_ORG}/${REPO}/branch_protections/${ENCODED_NAME}" 2>/dev/null || true
|
||||
|
||||
# Create rule
|
||||
RESPONSE=$(curl -sS -w "\n%{http_code}" \
|
||||
@@ -230,7 +230,7 @@ jobs:
|
||||
-H "Authorization: token ${GA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$RULE" \
|
||||
"${API}/repos/${GITEA_ORG}/${REPO}/branch_protections")
|
||||
"${API}/repos/${GIT_ORG}/${REPO}/branch_protections")
|
||||
|
||||
HTTP=$(echo "$RESPONSE" | tail -1)
|
||||
BODY=$(echo "$RESPONSE" | sed '$d')
|
||||
@@ -1,7 +1,7 @@
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# DEFGROUP: Git.Workflow
|
||||
# INGROUP: mokocli.Automation
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
# PATH: /.gitea/workflows/bulk-repo-sync.yml
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
id: args
|
||||
run: |
|
||||
ARGS="--org MokoConsulting"
|
||||
if [ "${{ inputs.dry_run }}" = "true" ] || [ "${{ gitea.event_name }}" = "schedule" ]; then
|
||||
if [ "${{ inputs.dry_run }}" = "true" ] || [ "${{ git.event_name }}" = "schedule" ]; then
|
||||
ARGS="$ARGS --dry-run"
|
||||
fi
|
||||
if [ -n "${{ inputs.repos }}" ]; then
|
||||
@@ -84,18 +84,18 @@ jobs:
|
||||
echo "Running: php automation/bulk_sync.php ${{ steps.args.outputs.args }}"
|
||||
php automation/bulk_sync.php ${{ steps.args.outputs.args }} 2>&1 | tee /tmp/bulk_sync.log
|
||||
env:
|
||||
GA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
GA_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
GH_TOKEN: ${{ secrets.GH_PAT }}
|
||||
GIT_PLATFORM: gitea
|
||||
GITEA_URL: https://git.mokoconsulting.tech
|
||||
GITEA_ORG: MokoConsulting
|
||||
GIT_PLATFORM: git
|
||||
GIT_URL: https://git.mokoconsulting.tech
|
||||
GIT_ORG: MokoConsulting
|
||||
|
||||
- name: Commit Updated Definitions
|
||||
if: success() && inputs.dry_run != 'true'
|
||||
run: |
|
||||
if [ -n "$(git status --porcelain definitions/sync/)" ]; then
|
||||
git config user.name "gitea-actions[bot]"
|
||||
git config user.email "gitea-actions[bot]@git.mokoconsulting.tech"
|
||||
git config user.name "git-actions[bot]"
|
||||
git config user.email "git-actions[bot]@git.mokoconsulting.tech"
|
||||
git add definitions/sync/*.def.tf
|
||||
git commit -m "chore: update synced repository definitions" || true
|
||||
git push || true
|
||||
@@ -112,9 +112,9 @@ jobs:
|
||||
bash automation/enforce_tags.sh || echo "Tag enforcement had errors (non-fatal)"
|
||||
fi
|
||||
env:
|
||||
GA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
GITEA_URL: https://git.mokoconsulting.tech
|
||||
GITEA_ORG: MokoConsulting
|
||||
GA_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
GIT_URL: https://git.mokoconsulting.tech
|
||||
GIT_ORG: MokoConsulting
|
||||
|
||||
- name: Upload Sync Log
|
||||
if: always() && github.server_url == 'https://github.com'
|
||||
@@ -124,7 +124,7 @@ jobs:
|
||||
path: /tmp/bulk_sync.log
|
||||
retention-days: 30
|
||||
|
||||
- name: Log Summary (Gitea)
|
||||
- name: Log Summary (Git)
|
||||
if: always() && github.server_url != 'https://github.com'
|
||||
run: |
|
||||
if [ -f /tmp/bulk_sync.log ]; then
|
||||
@@ -3,7 +3,7 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# DEFGROUP: Git.Workflow
|
||||
# INGROUP: mokocli.Automation
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
# PATH: /.gitea/workflows/renovate.yml
|
||||
@@ -41,8 +41,8 @@ on:
|
||||
default: false
|
||||
|
||||
env:
|
||||
GITEA_URL: https://git.mokoconsulting.tech
|
||||
GITEA_ORG: MokoConsulting
|
||||
GIT_URL: https://git.mokoconsulting.tech
|
||||
GIT_ORG: MokoConsulting
|
||||
RENOVATE_VERSION: '39'
|
||||
|
||||
permissions:
|
||||
@@ -57,11 +57,11 @@ jobs:
|
||||
- name: Determine target repos
|
||||
id: repos
|
||||
env:
|
||||
GA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
GA_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
run: |
|
||||
API="${GITEA_URL}/api/v1"
|
||||
API="${GIT_URL}/api/v1"
|
||||
|
||||
EXCLUDE="gitea-org-config org-profile gitea-private .mokogitea-private mokocli MokoTesting"
|
||||
EXCLUDE="git-org-config org-profile git-private .mokogit-private mokocli MokoTesting"
|
||||
EXCLUDE="$EXCLUDE MokoCli-Template-Client MokoCli-Template-Dolibarr MokoCli-Template-Generic MokoCli-Template-Joomla MokoDoliProjTemplate"
|
||||
|
||||
if [ -n "${{ inputs.repos }}" ]; then
|
||||
@@ -72,7 +72,7 @@ jobs:
|
||||
while true; do
|
||||
BATCH=$(curl -sS \
|
||||
-H "Authorization: token ${GA_TOKEN}" \
|
||||
"${API}/orgs/${GITEA_ORG}/repos?page=${PAGE}&limit=50" \
|
||||
"${API}/orgs/${GIT_ORG}/repos?page=${PAGE}&limit=50" \
|
||||
| jq -r '.[].name // empty')
|
||||
[ -z "$BATCH" ] && break
|
||||
REPOS="$REPOS $BATCH"
|
||||
@@ -94,9 +94,9 @@ jobs:
|
||||
REPO_LIST=""
|
||||
for REPO in $REPOS; do
|
||||
if [ -n "$REPO_LIST" ]; then
|
||||
REPO_LIST="${REPO_LIST},${GITEA_ORG}/${REPO}"
|
||||
REPO_LIST="${REPO_LIST},${GIT_ORG}/${REPO}"
|
||||
else
|
||||
REPO_LIST="${GITEA_ORG}/${REPO}"
|
||||
REPO_LIST="${GIT_ORG}/${REPO}"
|
||||
fi
|
||||
done
|
||||
|
||||
@@ -107,8 +107,8 @@ jobs:
|
||||
- name: Run Renovate
|
||||
if: steps.repos.outputs.repo_list != ''
|
||||
env:
|
||||
RENOVATE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
RENOVATE_PLATFORM: gitea
|
||||
RENOVATE_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
RENOVATE_PLATFORM: git
|
||||
RENOVATE_ENDPOINT: ${{ env.GITEA_URL }}/api/v1
|
||||
RENOVATE_GIT_AUTHOR: 'Renovate Bot <renovate@mokoconsulting.tech>'
|
||||
RENOVATE_REPOSITORIES: ${{ steps.repos.outputs.repo_list }}
|
||||
@@ -116,8 +116,8 @@ jobs:
|
||||
LOG_LEVEL: info
|
||||
run: |
|
||||
npx --yes renovate@${RENOVATE_VERSION} \
|
||||
--platform=gitea \
|
||||
--endpoint="${GITEA_URL}/api/v1" \
|
||||
--platform=git \
|
||||
--endpoint="${GIT_URL}/api/v1" \
|
||||
--token="${RENOVATE_TOKEN}" \
|
||||
--git-author="Renovate Bot <renovate@mokoconsulting.tech>" \
|
||||
--autodiscover=false \
|
||||
@@ -3,11 +3,11 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# DEFGROUP: Git.Workflow
|
||||
# INGROUP: mokocli.Maintenance
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
# PATH: /.gitea/workflows/sync-wikis.yml
|
||||
# BRIEF: Daily sync of all Gitea wikis to consolidated GitHub wiki repo
|
||||
# BRIEF: Daily sync of all Git wikis to consolidated GitHub wiki repo
|
||||
|
||||
name: Sync Wikis to GitHub
|
||||
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
- name: Sync all wikis
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_PAT }}
|
||||
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
GIT_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
run: |
|
||||
if [ -z "$GH_TOKEN" ]; then
|
||||
echo "::error::GH_TOKEN secret not set"
|
||||
@@ -3,10 +3,10 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: MokoGitea.Workflow
|
||||
# DEFGROUP: MokoGit.Workflow
|
||||
# INGROUP: MokoCLI.Release
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
|
||||
# PATH: /.mokogitea/workflows/auto-bump.yml
|
||||
# PATH: /.mokogit/workflows/auto-bump.yml
|
||||
# VERSION: 09.02.00
|
||||
# BRIEF: Auto patch-bump version on every push to dev (skips merge commits)
|
||||
|
||||
@@ -22,7 +22,7 @@ on:
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
MOKOGIT_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
with:
|
||||
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
token: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Setup MokoCLI tools
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
echo "MOKO_CLI=/opt/mokocli/cli" >> "$GITHUB_ENV"
|
||||
else
|
||||
git clone --depth 1 --branch main --quiet \
|
||||
"https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/MokoConsulting/mokocli.git" \
|
||||
"https://x-access-token:${{ secrets.MOKOGIT_TOKEN }}@git.mokoconsulting.tech/MokoConsulting/mokocli.git" \
|
||||
/tmp/mokocli
|
||||
cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet
|
||||
echo "MOKO_CLI=/tmp/mokocli/cli" >> "$GITHUB_ENV"
|
||||
@@ -63,5 +63,5 @@ jobs:
|
||||
run: |
|
||||
php ${MOKO_CLI}/version_auto_bump.php \
|
||||
--path . --branch "${GITHUB_REF_NAME}" \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
|
||||
--repo-url "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
||||
--token "${{ secrets.MOKOGIT_TOKEN }}" \
|
||||
--repo-url "https://x-access-token:${{ secrets.MOKOGIT_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
||||
@@ -3,10 +3,10 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: MokoGitea.Workflow
|
||||
# DEFGROUP: MokoGit.Workflow
|
||||
# INGROUP: MokoCLI.Release
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
|
||||
# PATH: /.mokogitea/workflows/auto-release.yml
|
||||
# PATH: /.mokogit/workflows/auto-release.yml
|
||||
# VERSION: 05.01.00
|
||||
# BRIEF: Universal build & release � detects platform from metadata API
|
||||
#
|
||||
@@ -31,7 +31,7 @@ on:
|
||||
branches:
|
||||
- main
|
||||
paths-ignore:
|
||||
- '.mokogitea/workflows/**'
|
||||
- '.mokogit/workflows/**'
|
||||
- '*.md'
|
||||
- 'wiki/**'
|
||||
- '.editorconfig'
|
||||
@@ -52,9 +52,9 @@ on:
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }}
|
||||
GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }}
|
||||
MOKOGIT_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
GIT_ORG: ${{ vars.GITEA_ORG || github.repository_owner }}
|
||||
GIT_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }}
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
@@ -77,13 +77,13 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
with:
|
||||
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
token: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
fetch-depth: 1
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup MokoCLI tools
|
||||
env:
|
||||
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
||||
run: |
|
||||
if [ -f /opt/mokocli/cli/version_bump.php ] && [ -f /opt/mokocli/vendor/autoload.php ]; then
|
||||
@@ -104,8 +104,8 @@ jobs:
|
||||
|
||||
- name: Rename branch to rc
|
||||
run: |
|
||||
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
AUTH="Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
API_BASE="${MOKOGIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}"
|
||||
AUTH="Authorization: token ${{ secrets.MOKOGIT_TOKEN }}"
|
||||
FROM="${{ github.event.pull_request.head.ref || 'dev' }}"
|
||||
PR="${{ github.event.pull_request.number }}"
|
||||
|
||||
@@ -115,12 +115,12 @@ jobs:
|
||||
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
|
||||
# Point rc at the source commit via git push. Git'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]"
|
||||
PUSH_URL="https://x-access-token:${{ secrets.MOKOGIT_TOKEN }}@${MOKOGIT_URL#https://}/${GIT_ORG}/${GIT_REPO}.git"
|
||||
git config --global user.name "mokogit-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" \
|
||||
@@ -144,28 +144,28 @@ jobs:
|
||||
- name: Trigger RC deploy
|
||||
run: |
|
||||
# Workflow-token pushes do NOT wake downstream workflows; dispatch deploy-rc explicitly.
|
||||
curl -sf -X POST -H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \n -H "Content-Type: application/json" \n "${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}/actions/workflows/deploy-rc.yml/dispatches" \n -d '{"ref":"rc"}' \n && echo "Dispatched deploy-rc on rc" \n || echo "::warning::deploy-rc dispatch failed (no deploy-rc.yml on rc? non-go platform)"
|
||||
curl -sf -X POST -H "Authorization: token ${{ secrets.MOKOGIT_TOKEN }}" \n -H "Content-Type: application/json" \n "${MOKOGIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}/actions/workflows/deploy-rc.yml/dispatches" \n -d '{"ref":"rc"}' \n && echo "Dispatched deploy-rc on rc" \n || echo "::warning::deploy-rc dispatch failed (no deploy-rc.yml on rc? non-go platform)"
|
||||
|
||||
- name: Checkout rc and configure git
|
||||
run: |
|
||||
git fetch origin rc
|
||||
git checkout rc
|
||||
git config --local user.email "mokogitea-actions[bot]@mokoconsulting.tech"
|
||||
git config --local user.name "mokogitea-actions[bot]"
|
||||
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
||||
git config --local user.email "mokogit-actions[bot]@mokoconsulting.tech"
|
||||
git config --local user.name "mokogit-actions[bot]"
|
||||
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGIT_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
||||
|
||||
- name: Publish RC release
|
||||
continue-on-error: true
|
||||
run: |
|
||||
php ${MOKO_CLI}/release_publish.php \
|
||||
--path . --stability rc --bump minor --branch rc \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
--token "${{ secrets.MOKOGIT_TOKEN }}"
|
||||
|
||||
- name: Update RC release notes from CHANGELOG.md
|
||||
continue-on-error: true
|
||||
run: |
|
||||
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
API_BASE="${MOKOGIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}"
|
||||
TOKEN="${{ secrets.MOKOGIT_TOKEN }}"
|
||||
|
||||
# Extract [Unreleased] section from changelog
|
||||
NOTES=""
|
||||
@@ -218,15 +218,15 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
with:
|
||||
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
token: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
|
||||
- name: Configure git for bot pushes
|
||||
run: |
|
||||
git config --local user.email "mokogitea-actions[bot]@mokoconsulting.tech"
|
||||
git config --local user.name "mokogitea-actions[bot]"
|
||||
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
||||
git config --local user.email "mokogit-actions[bot]@mokoconsulting.tech"
|
||||
git config --local user.name "mokogit-actions[bot]"
|
||||
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGIT_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
||||
|
||||
- name: Check for merge conflict markers
|
||||
run: |
|
||||
@@ -243,7 +243,7 @@ jobs:
|
||||
|
||||
- name: Setup MokoCLI tools
|
||||
env:
|
||||
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
||||
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_MIRROR_TOKEN }}"}}'
|
||||
run: |
|
||||
@@ -290,7 +290,7 @@ jobs:
|
||||
fi
|
||||
php ${MOKO_CLI}/release_publish.php \
|
||||
--path . --stability stable ${BUMP_FLAG} --branch main \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
--token "${{ secrets.MOKOGIT_TOKEN }}"
|
||||
|
||||
- name: "Read published version"
|
||||
id: version
|
||||
@@ -317,8 +317,8 @@ jobs:
|
||||
!startsWith(steps.platform.outputs.platform, 'joomla')
|
||||
run: |
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
API_BASE="${MOKOGIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}"
|
||||
TOKEN="${{ secrets.MOKOGIT_TOKEN }}"
|
||||
SEMVER_TAG="v${VERSION}"
|
||||
|
||||
echo "Creating semver tag: ${SEMVER_TAG}"
|
||||
@@ -342,8 +342,8 @@ jobs:
|
||||
|
||||
- name: Update release notes and promote changelog
|
||||
run: |
|
||||
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
API_BASE="${MOKOGIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}"
|
||||
TOKEN="${{ secrets.MOKOGIT_TOKEN }}"
|
||||
|
||||
# Get the stable release info (version and ID)
|
||||
RELEASE_JSON=$(curl -sf -H "Authorization: token ${TOKEN}" \
|
||||
@@ -445,10 +445,10 @@ jobs:
|
||||
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
|
||||
GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
|
||||
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
API_BASE="${MOKOGIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}"
|
||||
php ${MOKO_CLI}/release_mirror.php \
|
||||
--version "$VERSION" --tag "$RELEASE_TAG" \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
|
||||
--token "${{ secrets.MOKOGIT_TOKEN }}" --api-base "$API_BASE" \
|
||||
--gh-token "${{ secrets.GH_MIRROR_TOKEN }}" --gh-repo "$GH_REPO" \
|
||||
--branch main 2>&1 || true
|
||||
echo "GitHub mirror updated" >> $GITHUB_STEP_SUMMARY
|
||||
@@ -474,8 +474,8 @@ jobs:
|
||||
if: steps.version.outputs.skip != 'true'
|
||||
continue-on-error: true
|
||||
run: |
|
||||
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
API_BASE="${MOKOGIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}"
|
||||
TOKEN="${{ secrets.MOKOGIT_TOKEN }}"
|
||||
|
||||
# Delete rc branch (ephemeral — created by promote-rc)
|
||||
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
|
||||
@@ -490,8 +490,8 @@ jobs:
|
||||
if: steps.version.outputs.skip != 'true'
|
||||
continue-on-error: true
|
||||
run: |
|
||||
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
API_BASE="${MOKOGIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}"
|
||||
TOKEN="${{ secrets.MOKOGIT_TOKEN }}"
|
||||
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||
BRANCH_NAME="version/${VERSION}"
|
||||
MAIN_SHA=$(git rev-parse HEAD)
|
||||
@@ -511,9 +511,9 @@ jobs:
|
||||
if: steps.version.outputs.skip != 'true'
|
||||
continue-on-error: true
|
||||
run: |
|
||||
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
API_BASE="${MOKOGIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}"
|
||||
php ${MOKO_CLI}/version_reset_dev.php \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "${API_BASE}" \
|
||||
--token "${{ secrets.MOKOGIT_TOKEN }}" --api-base "${API_BASE}" \
|
||||
--branch dev --path . 2>&1 || true
|
||||
|
||||
# -- Summary --------------------------------------------------------------
|
||||
@@ -537,5 +537,5 @@ jobs:
|
||||
echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Branch | \`${{ steps.version.outputs.branch }}\` |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Tag | \`${{ steps.version.outputs.tag }}\` |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Release | [View](${MOKOGITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/${{ steps.version.outputs.tag }}) |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Release | [View](${MOKOGIT_URL}/${GIT_ORG}/${GIT_REPO}/releases/tag/${{ steps.version.outputs.tag }}) |" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
@@ -3,10 +3,10 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: MokoGitea.Workflow
|
||||
# DEFGROUP: MokoGit.Workflow
|
||||
# INGROUP: MokoCLI.Universal
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
|
||||
# PATH: /.mokogitea/workflows/branch-cleanup.yml
|
||||
# PATH: /.mokogit/workflows/branch-cleanup.yml
|
||||
# VERSION: 01.00.00
|
||||
# BRIEF: Delete feature branches after PR merge
|
||||
|
||||
@@ -37,7 +37,7 @@ jobs:
|
||||
ENCODED=$(printf '%s' "${BRANCH}" | sed 's|/|%2F|g')
|
||||
|
||||
STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X DELETE \
|
||||
-H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \
|
||||
-H "Authorization: token ${{ secrets.MOKOGIT_TOKEN }}" \
|
||||
"${API}/${ENCODED}" 2>/dev/null || true)
|
||||
|
||||
if [ "$STATUS" = "204" ]; then
|
||||
@@ -3,10 +3,10 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: MokoGitea.Workflow
|
||||
# DEFGROUP: MokoGit.Workflow
|
||||
# INGROUP: MokoCLI.Cascade
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
|
||||
# PATH: /.mokogitea/workflows/cascade-dev.yml
|
||||
# PATH: /.mokogit/workflows/cascade-dev.yml
|
||||
# VERSION: 02.01.00
|
||||
# BRIEF: Cascade main -> dev; auto-merge clean, auto-resolve VERSION-stamp-only conflicts, else notify
|
||||
|
||||
@@ -27,10 +27,10 @@ permissions:
|
||||
pull-requests: write
|
||||
|
||||
env:
|
||||
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
MOKOGIT_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' }}
|
||||
NTFY_TOPIC: ${{ vars.CASCADE_NTFY_TOPIC || vars.NTFY_TOPIC || 'git-releases' }}
|
||||
|
||||
jobs:
|
||||
cascade:
|
||||
@@ -41,15 +41,15 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
token: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
|
||||
- name: Cascade main -> dev (auto-resolve version stamps, else notify)
|
||||
env:
|
||||
TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
REPO: ${{ github.repository }}
|
||||
run: |
|
||||
set -uo pipefail
|
||||
API="${MOKOGITEA_URL}/api/v1/repos/${REPO}"
|
||||
API="${MOKOGIT_URL}/api/v1/repos/${REPO}"
|
||||
AUTH="Authorization: token ${TOKEN}"
|
||||
jqget() { python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('$1',''))" 2>/dev/null; }
|
||||
|
||||
@@ -86,12 +86,12 @@ jobs:
|
||||
-H "Title: ${REPO}: dev cascade needs manual merge" \
|
||||
-H "Tags: warning,twisted_rightwards_arrows" \
|
||||
-H "Priority: high" \
|
||||
-H "Click: ${MOKOGITEA_URL}/${REPO}/pulls/${PR}" \
|
||||
-H "Click: ${MOKOGIT_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)
|
||||
# 3. wait for MokoGit 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)
|
||||
@@ -115,7 +115,7 @@ jobs:
|
||||
|
||||
# 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.name "MokoGit Cascade"
|
||||
git config user.email "actions@mokoconsulting.tech"
|
||||
git fetch --quiet origin main dev
|
||||
git checkout -B dev origin/dev
|
||||
@@ -3,10 +3,10 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: MokoGitea.Workflow
|
||||
# DEFGROUP: MokoGit.Workflow
|
||||
# INGROUP: MokoCLI.CI
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
|
||||
# PATH: /.mokogitea/workflows/ci-generic.yml
|
||||
# PATH: /.mokogit/workflows/ci-generic.yml
|
||||
# VERSION: 01.00.00
|
||||
# BRIEF: CI pipeline — lint, validate, and test for generic projects (PHP + Node.js)
|
||||
|
||||
@@ -131,7 +131,7 @@ jobs:
|
||||
test:
|
||||
name: Tests
|
||||
runs-on: ubuntu-latest
|
||||
# Independent job (no `needs: lint`): the MokoGitea Actions scheduler does not
|
||||
# Independent job (no `needs: lint`): the MokoGit Actions scheduler does not
|
||||
# offer the dependent 2nd job of a needs-chain to runners, so it stalls in
|
||||
# "waiting" and is reaped by ABANDONED_JOB_TIMEOUT. Guard template repos
|
||||
# directly (same condition lint uses) instead of gating on lint's result.
|
||||
+9
-9
@@ -3,12 +3,12 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: MokoGitea.Workflow
|
||||
# DEFGROUP: MokoGit.Workflow
|
||||
# INGROUP: MokoCLI.Universal
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
|
||||
# PATH: /.mokogitea/workflows/ci-issue-reporter.yml
|
||||
# PATH: /.mokogit/workflows/ci-issue-reporter.yml
|
||||
# VERSION: 01.00.00
|
||||
# BRIEF: Reusable workflow — creates/updates a MokoGitea issue when a CI gate fails.
|
||||
# BRIEF: Reusable workflow — creates/updates a MokoGit issue when a CI gate fails.
|
||||
# Clones MokoCLI and runs cli/ci_issue_reporter.sh.
|
||||
|
||||
name: "Universal: CI Issue Reporter"
|
||||
@@ -35,7 +35,7 @@ on:
|
||||
type: string
|
||||
default: ""
|
||||
secrets:
|
||||
MOKOGITEA_TOKEN:
|
||||
MOKOGIT_TOKEN:
|
||||
required: true
|
||||
|
||||
env:
|
||||
@@ -49,16 +49,16 @@ jobs:
|
||||
steps:
|
||||
- name: Clone MokoCLI
|
||||
env:
|
||||
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
MOKOGIT_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
run: |
|
||||
MOKOGITEA_URL="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}"
|
||||
git clone --depth 1 --filter=blob:none --sparse "${MOKOGITEA_URL}/MokoConsulting/mokocli.git" /tmp/mokocli
|
||||
MOKOGIT_URL="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}"
|
||||
git clone --depth 1 --filter=blob:none --sparse "${MOKOGIT_URL}/MokoConsulting/mokocli.git" /tmp/mokocli
|
||||
cd /tmp/mokocli && git sparse-checkout set cli/ci_issue_reporter.sh
|
||||
|
||||
- name: Report CI failure
|
||||
env:
|
||||
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
MOKOGIT_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
MOKOGIT_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
run: |
|
||||
chmod +x /tmp/mokocli/cli/ci_issue_reporter.sh
|
||||
/tmp/mokocli/cli/ci_issue_reporter.sh \
|
||||
@@ -3,10 +3,10 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: MokoGitea.Workflow
|
||||
# DEFGROUP: MokoGit.Workflow
|
||||
# INGROUP: MokoCLI.Maintenance
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
# PATH: /.mokogitea/workflows/cleanup.yml
|
||||
# PATH: /.mokogit/workflows/cleanup.yml
|
||||
# VERSION: 01.00.00
|
||||
# BRIEF: Scheduled cleanup — delete merged branches and old workflow runs
|
||||
|
||||
@@ -21,7 +21,7 @@ permissions:
|
||||
contents: write
|
||||
|
||||
env:
|
||||
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
MOKOGIT_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
|
||||
jobs:
|
||||
cleanup:
|
||||
@@ -33,17 +33,17 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
token: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
|
||||
- name: Delete merged branches
|
||||
env:
|
||||
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
MOKOGIT_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
run: |
|
||||
echo "=== Merged Branch Cleanup ==="
|
||||
API="${MOKOGITEA_URL}/api/v1/repos/${{ github.repository }}"
|
||||
API="${MOKOGIT_URL}/api/v1/repos/${{ github.repository }}"
|
||||
|
||||
# List branches via API
|
||||
BRANCHES=$(curl -sS -H "Authorization: token ${MOKOGITEA_TOKEN}" \
|
||||
BRANCHES=$(curl -sS -H "Authorization: token ${MOKOGIT_TOKEN}" \
|
||||
"${API}/branches?limit=50" | jq -r '.[].name')
|
||||
|
||||
DELETED=0
|
||||
@@ -56,7 +56,7 @@ jobs:
|
||||
# Check if branch is merged into main
|
||||
if git merge-base --is-ancestor "origin/${BRANCH}" origin/main 2>/dev/null; then
|
||||
echo " Deleting merged branch: ${BRANCH}"
|
||||
curl -sS -X DELETE -H "Authorization: token ${MOKOGITEA_TOKEN}" \
|
||||
curl -sS -X DELETE -H "Authorization: token ${MOKOGIT_TOKEN}" \
|
||||
"${API}/branches/${BRANCH}" 2>/dev/null || true
|
||||
DELETED=$((DELETED + 1))
|
||||
fi
|
||||
@@ -66,20 +66,20 @@ jobs:
|
||||
|
||||
- name: Clean old workflow runs
|
||||
env:
|
||||
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
MOKOGIT_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
run: |
|
||||
echo "=== Workflow Run Cleanup ==="
|
||||
API="${MOKOGITEA_URL}/api/v1/repos/${{ github.repository }}"
|
||||
API="${MOKOGIT_URL}/api/v1/repos/${{ github.repository }}"
|
||||
CUTOFF=$(date -d "30 days ago" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -v-30d +%Y-%m-%dT%H:%M:%SZ)
|
||||
|
||||
# Get old completed runs
|
||||
RUNS=$(curl -sS -H "Authorization: token ${MOKOGITEA_TOKEN}" \
|
||||
RUNS=$(curl -sS -H "Authorization: token ${MOKOGIT_TOKEN}" \
|
||||
"${API}/actions/runs?status=completed&limit=50" | \
|
||||
jq -r ".workflow_runs[] | select(.created_at < \"${CUTOFF}\") | .id" 2>/dev/null)
|
||||
|
||||
DELETED=0
|
||||
for RUN_ID in $RUNS; do
|
||||
curl -sS -X DELETE -H "Authorization: token ${MOKOGITEA_TOKEN}" \
|
||||
curl -sS -X DELETE -H "Authorization: token ${MOKOGIT_TOKEN}" \
|
||||
"${API}/actions/runs/${RUN_ID}" 2>/dev/null || true
|
||||
DELETED=$((DELETED + 1))
|
||||
done
|
||||
+2
-2
@@ -27,7 +27,7 @@ jobs:
|
||||
- name: Checkout MokoCLI
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
with:
|
||||
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
token: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
|
||||
- name: Setup PHP
|
||||
run: |
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
DRY_RUN="--dry-run"
|
||||
fi
|
||||
php cli/branch_protect_org.php \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
|
||||
--token "${{ secrets.MOKOGIT_TOKEN }}" \
|
||||
--org "MokoConsulting" \
|
||||
$DRY_RUN
|
||||
|
||||
+6
-6
@@ -3,10 +3,10 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# DEFGROUP: Git.Workflow
|
||||
# INGROUP: mokocli.CI
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
# PATH: /.mokogitea/workflows/ci-platform.yml
|
||||
# PATH: /.mokogit/workflows/ci-platform.yml
|
||||
# VERSION: 09.23.00
|
||||
# BRIEF: mokocli CI — the standards engine validates itself
|
||||
#
|
||||
@@ -41,7 +41,7 @@ on:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- 'wiki/**'
|
||||
- '.mokogitea/ISSUE_TEMPLATE/**'
|
||||
- '.mokogit/ISSUE_TEMPLATE/**'
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
@@ -356,7 +356,7 @@ jobs:
|
||||
echo "::error file=${file}::Invalid YAML"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
done < <(find .mokogitea/workflows/ -name "*.yml" -o -name "*.yaml" 2>/dev/null | tr '\n' '\0')
|
||||
done < <(find .mokogit/workflows/ -name "*.yml" -o -name "*.yaml" 2>/dev/null | tr '\n' '\0')
|
||||
|
||||
{
|
||||
echo "### Template Integrity"
|
||||
@@ -453,8 +453,8 @@ jobs:
|
||||
needs.governance.result == 'failure' ||
|
||||
needs.templates.result == 'failure')
|
||||
env:
|
||||
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
MOKOGIT_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
MOKOGIT_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
run: |
|
||||
chmod +x automation/ci-issue-reporter.sh
|
||||
REPORTER="./automation/ci-issue-reporter.sh"
|
||||
+6
-6
@@ -13,7 +13,7 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
MOKOGIT_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
@@ -43,13 +43,13 @@ jobs:
|
||||
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||
echo "Package version: ${VERSION}"
|
||||
|
||||
# Gitea Composer Registry — auto-publishes from tags
|
||||
# Git Composer Registry — auto-publishes from tags
|
||||
# The tag push itself registers the package at:
|
||||
# https://git.mokoconsulting.tech/api/packages/MokoConsulting/composer
|
||||
- name: Verify Gitea registry
|
||||
- name: Verify Git registry
|
||||
run: |
|
||||
echo "Gitea Composer registry auto-publishes from tags."
|
||||
echo "Package available at: ${MOKOGITEA_URL}/api/packages/MokoConsulting/composer"
|
||||
echo "Git Composer registry auto-publishes from tags."
|
||||
echo "Package available at: ${MOKOGIT_URL}/api/packages/MokoConsulting/composer"
|
||||
echo "Install: composer require mokoconsulting/mokocli"
|
||||
|
||||
# Packagist — notify of new version (points to GitHub mirror which Packagist can access)
|
||||
@@ -72,5 +72,5 @@ jobs:
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Registry | Status |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "|----------|--------|" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Gitea | \`composer require mokoconsulting/mokocli:${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Git | \`composer require mokoconsulting/mokocli:${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Packagist | \`composer require mokoconsulting/mokocli\` |" >> $GITHUB_STEP_SUMMARY
|
||||
+7
-7
@@ -3,10 +3,10 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# DEFGROUP: Git.Workflow
|
||||
# INGROUP: mokocli.Automation
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
# PATH: /.mokogitea/workflows/sync-feature-versions.yml
|
||||
# PATH: /.mokogit/workflows/sync-feature-versions.yml
|
||||
# VERSION: 01.00.00
|
||||
# BRIEF: Merge dev into open feature branches after version bumps
|
||||
|
||||
@@ -22,7 +22,7 @@ permissions:
|
||||
contents: write
|
||||
|
||||
env:
|
||||
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
MOKOGIT_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
@@ -38,13 +38,13 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: dev
|
||||
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
token: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
|
||||
- name: Configure git
|
||||
run: |
|
||||
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"
|
||||
git config --local user.email "git-actions[bot]@mokoconsulting.tech"
|
||||
git config --local user.name "git-actions[bot]"
|
||||
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGIT_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
||||
|
||||
- name: Merge dev into feature branches
|
||||
run: |
|
||||
@@ -3,10 +3,10 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: MokoGitea.Workflow
|
||||
# DEFGROUP: MokoGit.Workflow
|
||||
# INGROUP: MokoCLI.Security
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
# PATH: /.mokogitea/workflows/gitleaks.yml
|
||||
# PATH: /.mokogit/workflows/gitleaks.yml
|
||||
# VERSION: 01.00.00
|
||||
# BRIEF: Secret scanning — detect leaked credentials, API keys, and tokens
|
||||
#
|
||||
@@ -34,7 +34,7 @@ permissions:
|
||||
|
||||
env:
|
||||
NTFY_URL: ${{ vars.NTFY_URL || 'https://ntfy.mokoconsulting.tech' }}
|
||||
NTFY_TOPIC: ${{ vars.NTFY_TOPIC || 'gitea-security' }}
|
||||
NTFY_TOPIC: ${{ vars.NTFY_TOPIC || 'git-security' }}
|
||||
|
||||
jobs:
|
||||
gitleaks:
|
||||
@@ -3,7 +3,7 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: MokoGitea.Workflow
|
||||
# DEFGROUP: MokoGit.Workflow
|
||||
# INGROUP: MokoCLI.Automation
|
||||
# VERSION: 01.00.00
|
||||
# BRIEF: Auto-create feature branch when an issue is opened
|
||||
@@ -19,7 +19,7 @@ permissions:
|
||||
issues: write
|
||||
|
||||
env:
|
||||
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
MOKOGIT_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
|
||||
jobs:
|
||||
create-branch:
|
||||
@@ -28,8 +28,8 @@ jobs:
|
||||
steps:
|
||||
- name: Create branch and comment
|
||||
run: |
|
||||
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
API="${MOKOGITEA_URL}/api/v1/repos/${{ github.repository }}"
|
||||
TOKEN="${{ secrets.MOKOGIT_TOKEN }}"
|
||||
API="${MOKOGIT_URL}/api/v1/repos/${{ github.repository }}"
|
||||
ISSUE_NUM="${{ github.event.issue.number }}"
|
||||
ISSUE_TITLE="${{ github.event.issue.title }}"
|
||||
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
echo "Created branch: ${BRANCH}"
|
||||
|
||||
# Comment on issue with branch link
|
||||
REPO_URL="${MOKOGITEA_URL}/${{ github.repository }}"
|
||||
REPO_URL="${MOKOGIT_URL}/${{ github.repository }}"
|
||||
BODY="Branch created: [\`${BRANCH}\`](${REPO_URL}/src/branch/${BRANCH})\n\n\`\`\`bash\ngit fetch origin\ngit checkout ${BRANCH}\n\`\`\`"
|
||||
|
||||
curl -sf -X POST \
|
||||
@@ -3,10 +3,10 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: MokoGitea.Workflow
|
||||
# DEFGROUP: MokoGit.Workflow
|
||||
# INGROUP: MokoCLI.Notifications
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
# PATH: /.mokogitea/workflows/notify.yml
|
||||
# PATH: /.mokogit/workflows/notify.yml
|
||||
# VERSION: 01.00.00
|
||||
# BRIEF: Push notifications via ntfy on release success or workflow failure
|
||||
|
||||
@@ -26,7 +26,7 @@ permissions:
|
||||
|
||||
env:
|
||||
NTFY_URL: ${{ vars.NTFY_URL || 'https://ntfy.mokoconsulting.tech' }}
|
||||
NTFY_TOPIC: ${{ vars.NTFY_TOPIC || 'gitea-releases' }}
|
||||
NTFY_TOPIC: ${{ vars.NTFY_TOPIC || 'git-releases' }}
|
||||
|
||||
jobs:
|
||||
notify:
|
||||
@@ -3,10 +3,10 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: MokoGitea.Workflow
|
||||
# DEFGROUP: MokoGit.Workflow
|
||||
# INGROUP: MokoCLI.CI
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
|
||||
# PATH: /.mokogitea/workflows/pr-check.yml
|
||||
# PATH: /.mokogit/workflows/pr-check.yml
|
||||
# VERSION: 09.23.00
|
||||
# BRIEF: PR gate — branch policy + code validation before merge
|
||||
|
||||
@@ -145,7 +145,7 @@ jobs:
|
||||
steps:
|
||||
- name: Remind to update the wiki
|
||||
env:
|
||||
TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
SERVER: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
REPO: ${{ github.repository }}
|
||||
PR: ${{ github.event.pull_request.number }}
|
||||
@@ -210,7 +210,7 @@ jobs:
|
||||
|
||||
- name: Check for merge conflict markers
|
||||
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 '<<<<<<< \|>>>>>>> \|^=======$' --exclude-dir='.git' --exclude-dir='.mokogit' --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
|
||||
echo "::error::Merge conflict markers found in source files"
|
||||
echo "## Conflict Markers Found" >> $GITHUB_STEP_SUMMARY
|
||||
@@ -224,7 +224,7 @@ jobs:
|
||||
- name: Detect platform
|
||||
id: platform
|
||||
run: |
|
||||
# Platform comes from the MokoGitea metadata API (public GET).
|
||||
# Platform comes from the MokoGit metadata API (public GET).
|
||||
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)"
|
||||
[ -z "$PLATFORM" ] && PLATFORM="generic"
|
||||
@@ -361,10 +361,10 @@ jobs:
|
||||
for ELEMENT in name version description; do
|
||||
grep -q "<${ELEMENT}>" "$MANIFEST" || { echo "::error::Missing <${ELEMENT}> in manifest"; exit 1; }
|
||||
done
|
||||
# Block legacy raw/branch update server URLs on MokoGitea
|
||||
RAW_URLS=$(grep -n 'raw/branch' "$MANIFEST" | grep -i 'mokoconsulting\|mokogitea\|git\.mokoconsulting\.tech' || true)
|
||||
# Block legacy raw/branch update server URLs on MokoGit
|
||||
RAW_URLS=$(grep -n 'raw/branch' "$MANIFEST" | grep -i 'mokoconsulting\|mokogit\|git\.mokoconsulting\.tech' || true)
|
||||
if [ -n "$RAW_URLS" ]; then
|
||||
echo "::error::Manifest contains legacy raw/branch update server URL on MokoGitea. Use the MokoGitea Pages URL instead (e.g. /{REPO}/updates.xml not /{REPO}/raw/branch/main/updates.xml)"
|
||||
echo "::error::Manifest contains legacy raw/branch update server URL on MokoGit. Use the MokoGit Pages URL instead (e.g. /{REPO}/updates.xml not /{REPO}/raw/branch/main/updates.xml)"
|
||||
echo "$RAW_URLS"
|
||||
exit 1
|
||||
fi
|
||||
@@ -578,12 +578,12 @@ jobs:
|
||||
steps:
|
||||
- name: Trigger RC pre-release
|
||||
env:
|
||||
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
MOKOGIT_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
REPO: ${{ github.repository }}
|
||||
BRANCH: ${{ github.head_ref }}
|
||||
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
MOKOGIT_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
run: |
|
||||
curl -s -X POST "${MOKOGITEA_URL}/api/v1/repos/${REPO}/actions/workflows/pre-release.yml/dispatches" -H "Authorization: token ${MOKOGITEA_TOKEN}" -H "Content-Type: application/json" -d "{\"ref\":\"${BRANCH}\",\"inputs\":{\"stability\":\"release-candidate\"}}"
|
||||
curl -s -X POST "${MOKOGIT_URL}/api/v1/repos/${REPO}/actions/workflows/pre-release.yml/dispatches" -H "Authorization: token ${MOKOGIT_TOKEN}" -H "Content-Type: application/json" -d "{\"ref\":\"${BRANCH}\",\"inputs\":{\"stability\":\"release-candidate\"}}"
|
||||
echo "### Pre-Release" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Triggered RC build on branch \`${BRANCH}\`" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
@@ -594,7 +594,7 @@ jobs:
|
||||
if: >-
|
||||
always() &&
|
||||
needs.validate.result == 'failure'
|
||||
uses: ./.mokogitea/workflows/ci-issue-reporter.yml
|
||||
uses: ./.mokogit/workflows/ci-issue-reporter.yml
|
||||
with:
|
||||
gate: "PR Validation"
|
||||
workflow: "PR Check"
|
||||
@@ -3,10 +3,10 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: MokoGitea.Workflow
|
||||
# DEFGROUP: MokoGit.Workflow
|
||||
# INGROUP: MokoCLI.Release
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
|
||||
# PATH: /.mokogitea/workflows/pre-release.yml
|
||||
# PATH: /.mokogit/workflows/pre-release.yml
|
||||
# VERSION: 05.02.01
|
||||
# BRIEF: Auto pre-release on push to dev/alpha/beta/rc branches
|
||||
|
||||
@@ -40,9 +40,9 @@ permissions:
|
||||
contents: write
|
||||
|
||||
env:
|
||||
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }}
|
||||
GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }}
|
||||
GIT_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
GIT_ORG: ${{ vars.GITEA_ORG || github.repository_owner }}
|
||||
GIT_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -61,7 +61,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
token: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
ref: ${{ github.ref_name }}
|
||||
submodules: recursive
|
||||
|
||||
@@ -71,7 +71,7 @@ jobs:
|
||||
|
||||
- name: Setup MokoCLI tools
|
||||
env:
|
||||
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
||||
run: |
|
||||
# Use pre-installed /opt/mokocli if available (updated by cron every 6h)
|
||||
@@ -156,9 +156,9 @@ jobs:
|
||||
fi
|
||||
|
||||
# Commit version bump
|
||||
git config --local user.email "mokogitea-actions[bot]@mokoconsulting.tech"
|
||||
git config --local user.name "mokogitea-actions[bot]"
|
||||
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
||||
git config --local user.email "mokogit-actions[bot]@mokoconsulting.tech"
|
||||
git config --local user.name "mokogit-actions[bot]"
|
||||
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGIT_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
||||
git add -A
|
||||
git diff --cached --quiet || {
|
||||
git commit -m "chore(version): pre-release bump to ${VERSION} [skip ci]"
|
||||
@@ -174,12 +174,12 @@ jobs:
|
||||
# Auto-detect element via manifest_element.php
|
||||
php ${MOKO_CLI}/manifest_element.php \
|
||||
--path . --version "$VERSION" --stability "$STABILITY" \
|
||||
--repo "${GITEA_REPO}" --github-output
|
||||
--repo "${GIT_REPO}" --github-output
|
||||
|
||||
# Read back element outputs
|
||||
EXT_ELEMENT=$(grep '^ext_element=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2)
|
||||
ZIP_NAME=$(grep '^zip_name=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2)
|
||||
[ -z "$EXT_ELEMENT" ] && EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
|
||||
[ -z "$EXT_ELEMENT" ] && EXT_ELEMENT=$(echo "${GIT_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
|
||||
[ -z "$ZIP_NAME" ] && ZIP_NAME="${EXT_ELEMENT}-${VERSION}.zip"
|
||||
|
||||
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||
@@ -197,18 +197,18 @@ jobs:
|
||||
run: |
|
||||
TAG="${{ steps.meta.outputs.tag }}"
|
||||
VERSION="${{ steps.meta.outputs.version }}"
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
API_BASE="${GIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}"
|
||||
php ${MOKO_CLI}/release_create.php \
|
||||
--path . --version "$VERSION" --tag "$TAG" \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
|
||||
--repo "${GITEA_REPO}" --branch "${{ github.ref_name }}" --prerelease
|
||||
--token "${{ secrets.MOKOGIT_TOKEN }}" --api-base "$API_BASE" \
|
||||
--repo "${GIT_REPO}" --branch "${{ github.ref_name }}" --prerelease
|
||||
|
||||
- name: Update release notes from CHANGELOG.md
|
||||
if: steps.eligibility.outputs.proceed == 'true'
|
||||
run: |
|
||||
TAG="${{ steps.meta.outputs.tag }}"
|
||||
VERSION="${{ steps.meta.outputs.version }}"
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
API_BASE="${GIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}"
|
||||
|
||||
# Extract [Unreleased] section from changelog (everything between [Unreleased] and next ## heading)
|
||||
if [ -f "CHANGELOG.md" ]; then
|
||||
@@ -219,7 +219,7 @@ jobs:
|
||||
fi
|
||||
|
||||
# Update release body via API
|
||||
RELEASE_ID=$(curl -sf -H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \
|
||||
RELEASE_ID=$(curl -sf -H "Authorization: token ${{ secrets.MOKOGIT_TOKEN }}" \
|
||||
"${API_BASE}/releases/tags/${TAG}" | python3 -c "import json,sys; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
|
||||
|
||||
if [ -n "$RELEASE_ID" ]; then
|
||||
@@ -231,7 +231,7 @@ jobs:
|
||||
'${API_BASE}/releases/${RELEASE_ID}',
|
||||
data=payload, method='PATCH',
|
||||
headers={
|
||||
'Authorization': 'token ${{ secrets.MOKOGITEA_TOKEN }}',
|
||||
'Authorization': 'token ${{ secrets.MOKOGIT_TOKEN }}',
|
||||
'Content-Type': 'application/json'
|
||||
})
|
||||
urllib.request.urlopen(req)
|
||||
@@ -245,21 +245,21 @@ jobs:
|
||||
run: |
|
||||
VERSION="${{ steps.meta.outputs.version }}"
|
||||
TAG="${{ steps.meta.outputs.tag }}"
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
API_BASE="${GIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}"
|
||||
php ${MOKO_CLI}/release_package.php \
|
||||
--path . --version "$VERSION" --tag "$TAG" \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
|
||||
--repo "${GITEA_REPO}" --output /tmp || true
|
||||
--token "${{ secrets.MOKOGIT_TOKEN }}" --api-base "$API_BASE" \
|
||||
--repo "${GIT_REPO}" --output /tmp || true
|
||||
|
||||
# updates.xml is generated dynamically by MokoGitea license server
|
||||
# updates.xml is generated dynamically by MokoGit license server
|
||||
# No need to build, commit, or sync updates.xml from workflows
|
||||
|
||||
- name: "Delete lesser pre-release channels (cascade)"
|
||||
if: steps.eligibility.outputs.proceed == 'true'
|
||||
continue-on-error: true
|
||||
run: |
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
API_BASE="${GIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}"
|
||||
TOKEN="${{ secrets.MOKOGIT_TOKEN }}"
|
||||
|
||||
php ${MOKO_CLI}/release_cascade.php \
|
||||
--stability "${{ steps.meta.outputs.stability }}" \
|
||||
@@ -3,10 +3,10 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: MokoGitea.Workflow
|
||||
# DEFGROUP: MokoGit.Workflow
|
||||
# INGROUP: MokoCLI.Universal
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
|
||||
# PATH: /.mokogitea/workflows/rc-revert.yml
|
||||
# PATH: /.mokogit/workflows/rc-revert.yml
|
||||
# VERSION: 09.23.00
|
||||
# BRIEF: Rename rc/ branch back to dev/ when PR is closed without merge
|
||||
|
||||
@@ -33,8 +33,8 @@ jobs:
|
||||
env:
|
||||
BRANCH: ${{ github.event.pull_request.head.ref }}
|
||||
REPO: ${{ github.repository }}
|
||||
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
GIT_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# BRANCH is attacker-controlled (PR head ref). Strict allowlist before ANY use.
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
fi
|
||||
SUFFIX="${BRANCH#rc/}"
|
||||
DEV_BRANCH="dev/${SUFFIX}"
|
||||
API="${GITEA_URL}/api/v1/repos/${REPO}/branches"
|
||||
API="${GIT_URL}/api/v1/repos/${REPO}/branches"
|
||||
|
||||
# Create dev/ branch from rc/ branch
|
||||
STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X POST \
|
||||
@@ -6,10 +6,10 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: MokoGitea.Workflow
|
||||
# DEFGROUP: MokoGit.Workflow
|
||||
# INGROUP: MokoCLI.Validation
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
|
||||
# PATH: /.mokogitea/workflows/repo-health.yml
|
||||
# PATH: /.mokogit/workflows/repo-health.yml
|
||||
# VERSION: 09.23.00
|
||||
# BRIEF: Enforces repository guardrails by validating scripts governance, tooling availability, and core repository health artifacts.
|
||||
# ============================================================================
|
||||
@@ -45,7 +45,7 @@ env:
|
||||
SCRIPTS_ALLOWED_DIRS: scripts,scripts/fix,scripts/lib,scripts/release,scripts/run,scripts/validate
|
||||
|
||||
# Repo health policy
|
||||
REPO_REQUIRED_ARTIFACTS: README.md,LICENSE,CHANGELOG.md,CONTRIBUTING.md,CODE_OF_CONDUCT.md,.mokogitea/workflows/
|
||||
REPO_REQUIRED_ARTIFACTS: README.md,LICENSE,CHANGELOG.md,CONTRIBUTING.md,CODE_OF_CONDUCT.md,.mokogit/workflows/
|
||||
REPO_OPTIONAL_FILES: SECURITY.md,GOVERNANCE.md,.editorconfig,.gitattributes,.gitignore,README.md,docs/
|
||||
REPO_DISALLOWED_DIRS:
|
||||
REPO_DISALLOWED_FILES: TODO.md,todo.md
|
||||
@@ -56,7 +56,7 @@ env:
|
||||
# File / directory variables
|
||||
DOCS_INDEX: docs/docs-index.md
|
||||
SCRIPT_DIR: scripts
|
||||
WORKFLOWS_DIR: .mokogitea/workflows
|
||||
WORKFLOWS_DIR: .mokogit/workflows
|
||||
SHELLCHECK_PATTERN: '*.sh'
|
||||
SPDX_FILE_GLOBS: '*.sh,*.php,*.js,*.ts,*.css,*.xml,*.yml,*.yaml'
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
@@ -77,7 +77,7 @@ jobs:
|
||||
- name: Check actor permission (admin only)
|
||||
id: perm
|
||||
env:
|
||||
TOKEN: ${{ secrets.MOKOGITEA_TOKEN || github.token }}
|
||||
TOKEN: ${{ secrets.MOKOGIT_TOKEN || github.token }}
|
||||
REPO: ${{ github.repository }}
|
||||
ACTOR: ${{ github.actor }}
|
||||
run: |
|
||||
@@ -88,14 +88,14 @@ jobs:
|
||||
|
||||
# Hardcoded authorized users — always allowed
|
||||
case "$ACTOR" in
|
||||
jmiller|mokogitea-actions[bot])
|
||||
jmiller|mokogit-actions[bot])
|
||||
ALLOWED=true
|
||||
PERMISSION=admin
|
||||
METHOD="hardcoded allowlist"
|
||||
;;
|
||||
*)
|
||||
# Detect platform and check permissions via API
|
||||
API_BASE="${GITHUB_API_URL:-${GITEA_API_URL:-https://api.github.com}}"
|
||||
API_BASE="${GITHUB_API_URL:-${GIT_API_URL:-https://api.github.com}}"
|
||||
RESP=$(curl -sf -H "Authorization: token ${TOKEN}" \
|
||||
"${API_BASE}/repos/${REPO}/collaborators/${ACTOR}/permission" 2>/dev/null || echo '{}')
|
||||
PERMISSION=$(echo "$RESP" | grep -oP '"permission"\s*:\s*"\K[^"]+' || echo "unknown")
|
||||
@@ -605,7 +605,7 @@ jobs:
|
||||
printf '%s\n' '| Domain | Status | Notes |'
|
||||
printf '%s\n' '|---|---|---|'
|
||||
printf '%s\n' '| Access control | OK | Admin-only execution gate |'
|
||||
printf '%s\n' '| Release policy | N/A | Releases handled by MokoGitea |'
|
||||
printf '%s\n' '| Release policy | N/A | Releases handled by MokoGit |'
|
||||
printf '%s\n' '| Scripts governance | OK | Directory policy and advisory reporting |'
|
||||
printf '%s\n' '| Repo required artifacts | OK | Required, optional, disallowed enforcement |'
|
||||
printf '%s\n' '| Repo content heuristics | OK | Brand, license, changelog structure |'
|
||||
@@ -677,7 +677,7 @@ jobs:
|
||||
if: >-
|
||||
always() &&
|
||||
needs.scripts_governance.result == 'failure'
|
||||
uses: ./.mokogitea/workflows/ci-issue-reporter.yml
|
||||
uses: ./.mokogit/workflows/ci-issue-reporter.yml
|
||||
with:
|
||||
gate: "Scripts Governance"
|
||||
workflow: "Repo Health"
|
||||
@@ -691,7 +691,7 @@ jobs:
|
||||
if: >-
|
||||
always() &&
|
||||
needs.repo_health.result == 'failure'
|
||||
uses: ./.mokogitea/workflows/ci-issue-reporter.yml
|
||||
uses: ./.mokogit/workflows/ci-issue-reporter.yml
|
||||
with:
|
||||
gate: "Repository Health"
|
||||
workflow: "Repo Health"
|
||||
+16
-16
@@ -4,7 +4,7 @@
|
||||
# DEFGROUP: GitHub.Workflow
|
||||
# INGROUP: MokoCLI.Compliance
|
||||
# REPO: https://github.com/mokoconsulting-tech/mokocli
|
||||
# PATH: /.mokogitea/workflows/standards-compliance.yml
|
||||
# PATH: /.mokogit/workflows/standards-compliance.yml
|
||||
# VERSION: 04.06.00
|
||||
# BRIEF: MokoCLI compliance validation workflow
|
||||
# NOTE: Validates repository structure, documentation, and coding standards
|
||||
@@ -299,7 +299,7 @@ jobs:
|
||||
echo "|-----------|--------|-------|------|-------|" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# Check required directories
|
||||
for dir in .mokogitea; do
|
||||
for dir in .mokogit; do
|
||||
if [ -d "$dir" ]; then
|
||||
FILE_COUNT=$(find "$dir" -type f 2>/dev/null | wc -l)
|
||||
DIR_SIZE=$(du -sh "$dir" 2>/dev/null | cut -f1)
|
||||
@@ -320,7 +320,7 @@ jobs:
|
||||
echo "### 🔴 Critical Issues: $MISSING" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Remediation Steps:**" >> $GITHUB_STEP_SUMMARY
|
||||
[ ! -d ".mokogitea" ] && echo "- Create .mokogitea directory: \`mkdir -p .mokogitea/workflows\`" >> $GITHUB_STEP_SUMMARY
|
||||
[ ! -d ".mokogit" ] && echo "- Create .mokogit directory: \`mkdir -p .mokogit/workflows\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "📚 Reference: [MokoCLI Repository Structure](https://github.com/mokoconsulting-tech/mokocli/tree/main/docs/policy/core-structure.md)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
@@ -563,17 +563,17 @@ jobs:
|
||||
set -x
|
||||
echo "### GitHub Actions Workflows" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
WORKFLOWS_DIR=".mokogitea/workflows"
|
||||
WORKFLOWS_DIR=".mokogit/workflows"
|
||||
|
||||
if [ ! -d "$WORKFLOWS_DIR" ]; then
|
||||
echo "❌ No workflows directory found" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### ❌ Validation Failed: Workflows Directory Missing" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Error:** .mokogitea/workflows directory is required for CI/CD automation" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Action Required:** Create .mokogitea/workflows directory and add GitHub Actions workflows" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Error:** .mokogit/workflows directory is required for CI/CD automation" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Action Required:** Create .mokogit/workflows directory and add GitHub Actions workflows" >> $GITHUB_STEP_SUMMARY
|
||||
echo ""
|
||||
echo "❌ ERROR: .mokogitea/workflows directory not found"
|
||||
echo "❌ ERROR: .mokogit/workflows directory not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -612,7 +612,7 @@ jobs:
|
||||
echo "### Workflow YAML Syntax" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
INVALID=0
|
||||
for workflow in $(find .mokogitea/workflows -maxdepth 1 -type f \( -name "*.yml" -o -name "*.yaml" \) 2>/dev/null); do
|
||||
for workflow in $(find .mokogit/workflows -maxdepth 1 -type f \( -name "*.yml" -o -name "*.yaml" \) 2>/dev/null); do
|
||||
if [ -f "$workflow" ]; then
|
||||
if python3 -c "import yaml, sys; yaml.safe_load(open(sys.argv[1]))" "$workflow" 2>/dev/null; then
|
||||
echo "✅ $(basename $workflow)" >> $GITHUB_STEP_SUMMARY
|
||||
@@ -629,7 +629,7 @@ jobs:
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Error:** $INVALID workflow file(s) have invalid YAML syntax" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Action Required:** Fix YAML syntax errors in the marked workflow files" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Tool:** Run \`python3 -c \"import yaml; yaml.safe_load(open('.mokogitea/workflows/FILE.yml'))\"\` locally" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Tool:** Run \`python3 -c \"import yaml; yaml.safe_load(open('.mokogit/workflows/FILE.yml'))\"\` locally" >> $GITHUB_STEP_SUMMARY
|
||||
echo ""
|
||||
echo "❌ ERROR: $INVALID workflow file(s) with invalid YAML syntax"
|
||||
exit 1
|
||||
@@ -641,7 +641,7 @@ jobs:
|
||||
echo "✅ SUCCESS: All workflow files passed YAML validation"
|
||||
|
||||
- name: Validate CodeQL Configuration
|
||||
if: hashFiles('.mokogitea/workflows/codeql-analysis.yml') != ''
|
||||
if: hashFiles('.mokogit/workflows/codeql-analysis.yml') != ''
|
||||
run: |
|
||||
set -e
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
@@ -649,7 +649,7 @@ jobs:
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# Inline validation (rewritten from Python to bash for PHP-only architecture)
|
||||
CODEQL_FILE=".mokogitea/workflows/codeql-analysis.yml"
|
||||
CODEQL_FILE=".mokogit/workflows/codeql-analysis.yml"
|
||||
|
||||
if [ ! -f "$CODEQL_FILE" ]; then
|
||||
echo "⚠️ CodeQL workflow file not found" >> $GITHUB_STEP_SUMMARY
|
||||
@@ -1186,7 +1186,7 @@ jobs:
|
||||
fi
|
||||
|
||||
# Run yamllint and count line-length warnings
|
||||
YAML_OUTPUT=$(yamllint .mokogitea/workflows/*.yml 2>&1 | grep "line too long" || true)
|
||||
YAML_OUTPUT=$(yamllint .mokogit/workflows/*.yml 2>&1 | grep "line too long" || true)
|
||||
if [ -n "$YAML_OUTPUT" ]; then
|
||||
YAML_VIOLATIONS=$(echo "$YAML_OUTPUT" | wc -l)
|
||||
echo "⚠️ Found $YAML_VIOLATIONS lines exceeding 180 characters in YAML files" >> $GITHUB_STEP_SUMMARY
|
||||
@@ -2130,17 +2130,17 @@ jobs:
|
||||
WARNINGS=0
|
||||
ERRORS=0
|
||||
|
||||
# 1. Check .mokogitea/config.tf location (not root override files)
|
||||
# 1. Check .mokogit/config.tf location (not root override files)
|
||||
echo "### Override Configuration Check" >> $GITHUB_STEP_SUMMARY
|
||||
LEGACY_OVERRIDES=$(find . -maxdepth 1 -name "*override*.tf" -o -name "MokoCLI.override.tf" 2>/dev/null | wc -l || echo 0)
|
||||
if [ "$LEGACY_OVERRIDES" -gt 0 ]; then
|
||||
echo "⚠️ Found legacy override files in root directory" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Expected Location**: .mokogitea/config.tf" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Expected Location**: .mokogit/config.tf" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Legacy files found**: $LEGACY_OVERRIDES" >> $GITHUB_STEP_SUMMARY
|
||||
WARNINGS=$((WARNINGS + 1))
|
||||
else
|
||||
if [ -f ".mokogitea/config.tf" ]; then
|
||||
echo "✅ Override configuration in correct location (.mokogitea/config.tf)" >> $GITHUB_STEP_SUMMARY
|
||||
if [ -f ".mokogit/config.tf" ]; then
|
||||
echo "✅ Override configuration in correct location (.mokogit/config.tf)" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "ℹ️ No override configuration found" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
@@ -3,10 +3,10 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: MokoGitea.Workflow.Template
|
||||
# DEFGROUP: MokoGit.Workflow.Template
|
||||
# INGROUP: MokoCLI.CI
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Joomla
|
||||
# PATH: /.mokogitea/workflows/version-set.yml
|
||||
# PATH: /.mokogit/workflows/version-set.yml
|
||||
# VERSION: 01.00.00
|
||||
# BRIEF: Set or reset the extension version across all version-bearing files
|
||||
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.MOKOGITEA_TOKEN || github.token }}
|
||||
token: ${{ secrets.MOKOGIT_TOKEN || github.token }}
|
||||
ref: ${{ inputs.branch || github.ref }}
|
||||
fetch-depth: 1
|
||||
|
||||
+2
-2
@@ -34,7 +34,7 @@ feature/* ──PR──> dev ──draft PR──> (renamed to rc) ──merge
|
||||
7. **Merging to main** triggers the stable release pipeline:
|
||||
- Minor version bump (e.g., `02.09.xx` → `02.10.00`)
|
||||
- Stability suffix stripped (clean version)
|
||||
- MokoGitea release created with ZIP/tar.gz packages
|
||||
- MokoGit release created with ZIP/tar.gz packages
|
||||
- `updates.xml` updated (Joomla extensions)
|
||||
- `dev` branch recreated from `main`
|
||||
|
||||
@@ -119,7 +119,7 @@ This ensures Joomla sites on ANY stability channel see the update (Joomla only s
|
||||
|
||||
The version tools update all files containing version stamps:
|
||||
|
||||
- `.mokogitea/manifest.xml` (canonical source)
|
||||
- `.mokogit/manifest.xml` (canonical source)
|
||||
- Joomla XML manifests (`<version>` tag)
|
||||
- `README.md`, `CHANGELOG.md` (`VERSION:` pattern)
|
||||
- `package.json`, `pyproject.toml`
|
||||
|
||||
@@ -16,7 +16,7 @@ BRIEF: Project overview and documentation
|
||||
|
||||
PHP implementation of mokocli — enterprise standards, automation framework, workflow templates, and bulk sync tooling.
|
||||
|
||||
> **Primary platform**: [MokoGitea — git.mokoconsulting.tech](https://git.mokoconsulting.tech/MokoConsulting/MokoCli-API)
|
||||
> **Primary platform**: [MokoGit — git.mokoconsulting.tech](https://git.mokoconsulting.tech/MokoConsulting/MokoCli-API)
|
||||
> **Backup mirror**: [GitHub](https://github.com/MokoConsulting/MokoCli-API) *(read-only mirror)*
|
||||
|
||||
## What Lives Here
|
||||
@@ -25,7 +25,7 @@ PHP implementation of mokocli — enterprise standards, automation framework, wo
|
||||
|-----------|---------|
|
||||
| `lib/Enterprise/` | 38 PHP enterprise library classes (platform adapters, sync, validation, plugins) |
|
||||
| `cli/` | CLI scripts (archive, create, release, sync rulesets, version management) |
|
||||
| `automation/` | Bulk sync, push files, repo cleanup, MokoGitea migration |
|
||||
| `automation/` | Bulk sync, push files, repo cleanup, MokoGit migration |
|
||||
| `validate/` | 18 validation scripts (health, structure, secrets, syntax, drift) |
|
||||
| `templates/` | **Workflow templates** and config templates synced to governed repos |
|
||||
| `definitions/` | Repository structure definitions (`.tf` format) |
|
||||
@@ -42,7 +42,7 @@ composer require mokoconsulting-tech/enterprise
|
||||
|
||||
### Composer Registry
|
||||
|
||||
This package is served from MokoGitea package registry. Add this to your `composer.json`:
|
||||
This package is served from MokoGit package registry. Add this to your `composer.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -72,11 +72,11 @@ vendor/bin/moko inventory -- --path .
|
||||
|
||||
| Variable | Purpose |
|
||||
|----------|---------|
|
||||
| `GIT_PLATFORM` | `gitea` (default) or `github` |
|
||||
| `GA_TOKEN` | MokoGitea API / MokoGitea Actions token |
|
||||
| `GIT_PLATFORM` | `git` (default) or `github` |
|
||||
| `GA_TOKEN` | MokoGit API / MokoGit Actions token |
|
||||
| `GH_TOKEN` | GitHub API token (for mirror sync) |
|
||||
| `GITEA_URL` | MokoGitea instance URL (default: `https://git.mokoconsulting.tech`) |
|
||||
| `GITEA_ORG` | MokoGitea organization (default: `MokoConsulting`) |
|
||||
| `GIT_URL` | MokoGit instance URL (default: `https://git.mokoconsulting.tech`) |
|
||||
| `GIT_ORG` | MokoGit organization (default: `MokoConsulting`) |
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*
|
||||
* COMMANDS (run `php bin/moko list` for the full list — 97 commands)
|
||||
*
|
||||
* Automation sync, automation:cleanup, automation:migrate-gitea
|
||||
* Automation sync, automation:cleanup, automation:migrate-git
|
||||
* Validation health, detect, drift, check:syntax, check:version, ...
|
||||
* Release release, release:joomla, release:create, release:publish, ...
|
||||
* Version version:read, version:bump, version:auto-bump, ...
|
||||
@@ -91,7 +91,7 @@ const COMMAND_MAP = [
|
||||
'sync' => 'automation/bulk_sync.php',
|
||||
'deps:update' => 'automation/update_dependencies.php',
|
||||
'automation:cleanup' => 'automation/repo_cleanup.php',
|
||||
'automation:migrate-gitea' => 'automation/migrate_to_gitea.php',
|
||||
'automation:migrate-git' => 'automation/migrate_to_git.php',
|
||||
|
||||
// Maintenance
|
||||
'inventory' => 'maintenance/update_repo_inventory.php',
|
||||
|
||||
@@ -25,7 +25,7 @@ if (isset($options['help']) || empty($options['token'])) {
|
||||
echo "Usage: php cli/branch_protect_org.php --token TOKEN [--org ORG] [--api-base URL] [--dry-run]\n";
|
||||
echo "\n";
|
||||
echo "Options:\n";
|
||||
echo " --token Gitea API token (required)\n";
|
||||
echo " --token Git API token (required)\n";
|
||||
echo " --org Organization name (default: MokoConsulting)\n";
|
||||
echo " --api-base API base URL (default: https://git.mokoconsulting.tech/api/v1)\n";
|
||||
echo " --dry-run Show what would be changed without making changes\n";
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/branch_rename.php
|
||||
* VERSION: 09.43.00
|
||||
* BRIEF: Rename a git branch via Gitea API (create new, update PR, delete old)
|
||||
* BRIEF: Rename a git branch via Git API (create new, update PR, delete old)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
@@ -24,7 +24,7 @@ class BranchRenameCli extends CliFramework
|
||||
{
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setDescription('Rename a git branch via Gitea API (create new, update PR, delete old)');
|
||||
$this->setDescription('Rename a git branch via Git API (create new, update PR, delete old)');
|
||||
$this->addArgument('--from', 'Source branch name', '');
|
||||
$this->addArgument('--to', 'Target branch name', '');
|
||||
$this->addArgument('--token', 'API token', '');
|
||||
|
||||
+18
-18
@@ -13,7 +13,7 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/bulk_workflow_push.php
|
||||
* VERSION: 09.43.00
|
||||
* BRIEF: Push a workflow file to all governed repos via the Gitea Contents API
|
||||
* BRIEF: Push a workflow file to all governed repos via the Git Contents API
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
@@ -31,18 +31,18 @@ class BulkWorkflowPushCli extends CliFramework
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setDescription('Push a workflow file to all governed repos via the Gitea Contents API');
|
||||
$this->addArgument('--gitea-url', 'Gitea URL (default: https://git.mokoconsulting.tech)', 'https://git.mokoconsulting.tech');
|
||||
$this->addArgument('--token', 'Gitea API token', '');
|
||||
$this->setDescription('Push a workflow file to all governed repos via the Git Contents API');
|
||||
$this->addArgument('--git-url', 'Git URL (default: https://git.mokoconsulting.tech)', 'https://git.mokoconsulting.tech');
|
||||
$this->addArgument('--token', 'Git API token', '');
|
||||
$this->addArgument('--org', 'Target organization', '');
|
||||
$this->addArgument('--file', 'Local workflow file to push', '');
|
||||
$this->addArgument('--dest', 'Destination path in repos (default: .mokogitea/workflows/<filename>)', '');
|
||||
$this->addArgument('--dest', 'Destination path in repos (default: .mokogit/workflows/<filename>)', '');
|
||||
$this->addArgument('--branch', 'Target branch (default: main)', 'main');
|
||||
}
|
||||
|
||||
protected function run(): int
|
||||
{
|
||||
$giteaUrl = rtrim($this->getArgument('--gitea-url'), '/');
|
||||
$gitUrl = rtrim($this->getArgument('--git-url'), '/');
|
||||
$token = $this->getArgument('--token');
|
||||
$org = $this->getArgument('--org');
|
||||
$workflowFile = $this->getArgument('--file');
|
||||
@@ -70,7 +70,7 @@ class BulkWorkflowPushCli extends CliFramework
|
||||
}
|
||||
|
||||
if ($destPath === '') {
|
||||
$destPath = '.mokogitea/workflows/' . basename($workflowFile);
|
||||
$destPath = '.mokogit/workflows/' . basename($workflowFile);
|
||||
}
|
||||
|
||||
$localContent = file_get_contents($workflowFile);
|
||||
@@ -82,7 +82,7 @@ class BulkWorkflowPushCli extends CliFramework
|
||||
|
||||
$this->log('INFO', "Pushing: {$workflowFile}");
|
||||
$this->log('INFO', " -> {$destPath} (branch: {$branch})");
|
||||
$this->log('INFO', " -> Org: {$org} @ {$giteaUrl}");
|
||||
$this->log('INFO', " -> Org: {$org} @ {$gitUrl}");
|
||||
|
||||
if ($this->dryRun) {
|
||||
$this->log('INFO', '[DRY RUN] No changes will be made.');
|
||||
@@ -90,7 +90,7 @@ class BulkWorkflowPushCli extends CliFramework
|
||||
|
||||
echo "\n";
|
||||
|
||||
$repos = $this->fetchOrgRepos($giteaUrl, $token, $org);
|
||||
$repos = $this->fetchOrgRepos($gitUrl, $token, $org);
|
||||
|
||||
if ($repos === null) {
|
||||
return 1;
|
||||
@@ -104,7 +104,7 @@ class BulkWorkflowPushCli extends CliFramework
|
||||
$encodedContent = base64_encode($localContent);
|
||||
|
||||
foreach ($repos as $repo) {
|
||||
$this->pushToRepo($giteaUrl, $token, $repo, $encodedContent, $localContent, $destPath, $branch);
|
||||
$this->pushToRepo($gitUrl, $token, $repo, $encodedContent, $localContent, $destPath, $branch);
|
||||
}
|
||||
|
||||
echo "\n";
|
||||
@@ -115,7 +115,7 @@ class BulkWorkflowPushCli extends CliFramework
|
||||
}
|
||||
|
||||
private function pushToRepo(
|
||||
string $giteaUrl,
|
||||
string $gitUrl,
|
||||
string $token,
|
||||
string $repoFullName,
|
||||
string $encodedContent,
|
||||
@@ -126,7 +126,7 @@ class BulkWorkflowPushCli extends CliFramework
|
||||
[$owner, $repoName] = explode('/', $repoFullName, 2);
|
||||
|
||||
$existing = $this->apiRequest(
|
||||
$giteaUrl,
|
||||
$gitUrl,
|
||||
$token,
|
||||
'GET',
|
||||
"/api/v1/repos/{$owner}/{$repoName}/contents/"
|
||||
@@ -159,7 +159,7 @@ class BulkWorkflowPushCli extends CliFramework
|
||||
]);
|
||||
|
||||
$response = $this->apiRequest(
|
||||
$giteaUrl,
|
||||
$gitUrl,
|
||||
$token,
|
||||
'PUT',
|
||||
"/api/v1/repos/{$owner}/{$repoName}/contents/"
|
||||
@@ -189,7 +189,7 @@ class BulkWorkflowPushCli extends CliFramework
|
||||
]);
|
||||
|
||||
$response = $this->apiRequest(
|
||||
$giteaUrl,
|
||||
$gitUrl,
|
||||
$token,
|
||||
'POST',
|
||||
"/api/v1/repos/{$owner}/{$repoName}/contents/"
|
||||
@@ -210,7 +210,7 @@ class BulkWorkflowPushCli extends CliFramework
|
||||
}
|
||||
}
|
||||
|
||||
private function fetchOrgRepos(string $giteaUrl, string $token, string $org): ?array
|
||||
private function fetchOrgRepos(string $gitUrl, string $token, string $org): ?array
|
||||
{
|
||||
$this->log('INFO', "Fetching repos from org: {$org}");
|
||||
|
||||
@@ -219,7 +219,7 @@ class BulkWorkflowPushCli extends CliFramework
|
||||
|
||||
while (true) {
|
||||
$response = $this->apiRequest(
|
||||
$giteaUrl,
|
||||
$gitUrl,
|
||||
$token,
|
||||
'GET',
|
||||
"/api/v1/orgs/{$org}/repos?"
|
||||
@@ -261,13 +261,13 @@ class BulkWorkflowPushCli extends CliFramework
|
||||
}
|
||||
|
||||
private function apiRequest(
|
||||
string $giteaUrl,
|
||||
string $gitUrl,
|
||||
string $token,
|
||||
string $method,
|
||||
string $endpoint,
|
||||
?string $body = null
|
||||
): array {
|
||||
$url = $giteaUrl . $endpoint;
|
||||
$url = $gitUrl . $endpoint;
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
|
||||
@@ -24,7 +24,7 @@ use MokoCli\CliFramework;
|
||||
|
||||
class BulkWorkflowTriggerCli extends CliFramework
|
||||
{
|
||||
private string $giteaUrl = 'https://git.mokoconsulting.tech';
|
||||
private string $gitUrl = 'https://git.mokoconsulting.tech';
|
||||
private string $token = '';
|
||||
private string $reposFile = '';
|
||||
private string $org = '';
|
||||
@@ -35,8 +35,8 @@ class BulkWorkflowTriggerCli extends CliFramework
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setDescription('Trigger a workflow across multiple repos at once');
|
||||
$this->addArgument('--gitea-url', 'Gitea URL (default: https://git.mokoconsulting.tech)', 'https://git.mokoconsulting.tech');
|
||||
$this->addArgument('--token', 'Gitea API token', '');
|
||||
$this->addArgument('--git-url', 'Git URL (default: https://git.mokoconsulting.tech)', 'https://git.mokoconsulting.tech');
|
||||
$this->addArgument('--token', 'Git API token', '');
|
||||
$this->addArgument('--repos', 'File with newline-separated owner/repo list', '');
|
||||
$this->addArgument('--org', 'Trigger on all repos in an org', '');
|
||||
$this->addArgument('--workflow', 'Workflow file (e.g., "sync-servers.yml")', '');
|
||||
@@ -46,7 +46,7 @@ class BulkWorkflowTriggerCli extends CliFramework
|
||||
|
||||
protected function run(): int
|
||||
{
|
||||
$this->giteaUrl = rtrim($this->getArgument('--gitea-url'), '/');
|
||||
$this->gitUrl = rtrim($this->getArgument('--git-url'), '/');
|
||||
$this->token = $this->getArgument('--token');
|
||||
$this->reposFile = $this->getArgument('--repos');
|
||||
$this->org = $this->getArgument('--org');
|
||||
@@ -78,7 +78,7 @@ class BulkWorkflowTriggerCli extends CliFramework
|
||||
}
|
||||
|
||||
$this->log('INFO', "Triggering workflow \"{$this->workflow}\" on ref \"{$this->ref}\" across " . count($repos) . " repo(s).");
|
||||
$this->log('INFO', "Gitea URL: {$this->giteaUrl}");
|
||||
$this->log('INFO', "Git URL: {$this->gitUrl}");
|
||||
|
||||
if ($this->dryRun) {
|
||||
$this->log('INFO', '[DRY RUN] No requests will be sent.');
|
||||
@@ -209,7 +209,7 @@ class BulkWorkflowTriggerCli extends CliFramework
|
||||
|
||||
private function apiRequest(string $method, string $endpoint, ?string $body = null): array
|
||||
{
|
||||
$url = $this->giteaUrl . $endpoint;
|
||||
$url = $this->gitUrl . $endpoint;
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
|
||||
+19
-19
@@ -10,7 +10,7 @@
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoCLI
|
||||
# PATH: /cli/ci_issue_reporter.sh
|
||||
# VERSION: 10.00.00
|
||||
# BRIEF: Creates or updates a Gitea issue when a CI gate fails.
|
||||
# BRIEF: Creates or updates a Git issue when a CI gate fails.
|
||||
# Deduplicates by searching open issues with the "ci-auto" label
|
||||
# whose title matches the gate. If a matching issue exists, a comment
|
||||
# is appended instead of opening a duplicate.
|
||||
@@ -19,10 +19,10 @@
|
||||
set -euo pipefail
|
||||
|
||||
# ── Defaults ────────────────────────────────────────────────────────────────
|
||||
MOKOGITEA_URL="${MOKOGITEA_URL:-https://git.mokoconsulting.tech}"
|
||||
MOKOGITEA_TOKEN="${MOKOGITEA_TOKEN:-}"
|
||||
MOKOGIT_URL="${MOKOGIT_URL:-https://git.mokoconsulting.tech}"
|
||||
MOKOGIT_TOKEN="${MOKOGIT_TOKEN:-}"
|
||||
REPO="${GITHUB_REPOSITORY:-}"
|
||||
RUN_URL="${GITHUB_SERVER_URL:-${MOKOGITEA_URL}}/${REPO}/actions/runs/${GITHUB_RUN_ID:-0}"
|
||||
RUN_URL="${GITHUB_SERVER_URL:-${MOKOGIT_URL}}/${REPO}/actions/runs/${GITHUB_RUN_ID:-0}"
|
||||
LABEL_NAME="ci-auto"
|
||||
LABEL_COLOR="#e11d48"
|
||||
|
||||
@@ -45,8 +45,8 @@ Optional:
|
||||
--workflow Workflow name for the issue title
|
||||
--repo owner/repo (default: \$GITHUB_REPOSITORY)
|
||||
--run-url URL to the CI run (auto-detected from env)
|
||||
--token Gitea API token (default: \$MOKOGITEA_TOKEN)
|
||||
--url Gitea base URL (default: \$MOKOGITEA_URL)
|
||||
--token Git API token (default: \$MOKOGIT_TOKEN)
|
||||
--url Git base URL (default: \$MOKOGIT_URL)
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
@@ -59,8 +59,8 @@ while [[ $# -gt 0 ]]; do
|
||||
--workflow) WORKFLOW="$2"; shift 2 ;;
|
||||
--repo) REPO="$2"; shift 2 ;;
|
||||
--run-url) RUN_URL="$2"; shift 2 ;;
|
||||
--token) MOKOGITEA_TOKEN="$2"; shift 2 ;;
|
||||
--url) MOKOGITEA_URL="$2"; shift 2 ;;
|
||||
--token) MOKOGIT_TOKEN="$2"; shift 2 ;;
|
||||
--url) MOKOGIT_URL="$2"; shift 2 ;;
|
||||
-h|--help) usage ;;
|
||||
*) echo "Unknown option: $1"; usage ;;
|
||||
esac
|
||||
@@ -68,10 +68,10 @@ done
|
||||
|
||||
[[ -z "$GATE" ]] && { echo "ERROR: --gate is required"; usage; }
|
||||
[[ -z "$DETAILS" ]] && { echo "ERROR: --details is required"; usage; }
|
||||
[[ -z "$MOKOGITEA_TOKEN" ]] && { echo "ERROR: MOKOGITEA_TOKEN not set"; exit 1; }
|
||||
[[ -z "$MOKOGIT_TOKEN" ]] && { echo "ERROR: MOKOGIT_TOKEN not set"; exit 1; }
|
||||
[[ -z "$REPO" ]] && { echo "ERROR: GITHUB_REPOSITORY not set"; exit 1; }
|
||||
|
||||
API="${MOKOGITEA_URL}/api/v1/repos/${REPO}"
|
||||
API="${MOKOGIT_URL}/api/v1/repos/${REPO}"
|
||||
|
||||
# ── Build title ─────────────────────────────────────────────────────────────
|
||||
if [[ -n "$WORKFLOW" ]]; then
|
||||
@@ -84,19 +84,19 @@ fi
|
||||
ensure_label() {
|
||||
local exists
|
||||
exists=$(curl -sf -o /dev/null -w '%{http_code}' \
|
||||
-H "Authorization: token ${MOKOGITEA_TOKEN}" \
|
||||
-H "Authorization: token ${MOKOGIT_TOKEN}" \
|
||||
"${API}/labels" 2>/dev/null || echo "000")
|
||||
|
||||
if [[ "$exists" == "200" ]]; then
|
||||
local found
|
||||
found=$(curl -sf \
|
||||
-H "Authorization: token ${MOKOGITEA_TOKEN}" \
|
||||
-H "Authorization: token ${MOKOGIT_TOKEN}" \
|
||||
"${API}/labels" 2>/dev/null \
|
||||
| grep -o "\"name\":\"${LABEL_NAME}\"" || true)
|
||||
|
||||
if [[ -z "$found" ]]; then
|
||||
curl -sf -X POST \
|
||||
-H "Authorization: token ${MOKOGITEA_TOKEN}" \
|
||||
-H "Authorization: token ${MOKOGIT_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API}/labels" \
|
||||
-d "{\"name\":\"${LABEL_NAME}\",\"color\":\"${LABEL_COLOR}\",\"description\":\"Auto-created by CI issue reporter\"}" \
|
||||
@@ -112,7 +112,7 @@ find_existing_issue() {
|
||||
|
||||
local response
|
||||
response=$(curl -sf \
|
||||
-H "Authorization: token ${MOKOGITEA_TOKEN}" \
|
||||
-H "Authorization: token ${MOKOGIT_TOKEN}" \
|
||||
"${API}/issues?type=issues&state=open&labels=${LABEL_NAME}&q=${query}&limit=5" \
|
||||
2>/dev/null || echo "[]")
|
||||
|
||||
@@ -148,7 +148,7 @@ ${DETAILS}
|
||||
Fix the issue described above and push a new commit. This issue will be closed automatically when the gate passes, or can be closed manually.
|
||||
|
||||
---
|
||||
*Auto-created by [ci-issue-reporter](${MOKOGITEA_URL}/MokoConsulting/MokoCLI/src/branch/main/cli/ci_issue_reporter.sh)*
|
||||
*Auto-created by [ci-issue-reporter](${MOKOGIT_URL}/MokoConsulting/MokoCLI/src/branch/main/cli/ci_issue_reporter.sh)*
|
||||
BODY
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ import sys, json
|
||||
print(json.dumps({'body': sys.stdin.read()}))" 2>/dev/null)
|
||||
|
||||
HTTP=$(curl -sf -o /dev/null -w '%{http_code}' -X POST \
|
||||
-H "Authorization: token ${MOKOGITEA_TOKEN}" \
|
||||
-H "Authorization: token ${MOKOGIT_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API}/issues/${EXISTING}/comments" \
|
||||
-d "${COMMENT_JSON}" 2>/dev/null || echo "000")
|
||||
@@ -199,7 +199,7 @@ print(json.dumps({
|
||||
}))" "$TITLE" <<< "$ISSUE_BODY" 2>/dev/null)
|
||||
|
||||
RESPONSE=$(curl -sf -X POST \
|
||||
-H "Authorization: token ${MOKOGITEA_TOKEN}" \
|
||||
-H "Authorization: token ${MOKOGIT_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API}/issues" \
|
||||
-d "${ISSUE_JSON}" 2>/dev/null || echo "{}")
|
||||
@@ -208,14 +208,14 @@ print(json.dumps({
|
||||
|
||||
if [[ -n "$ISSUE_NUM" ]]; then
|
||||
LABEL_ID=$(curl -sf \
|
||||
-H "Authorization: token ${MOKOGITEA_TOKEN}" \
|
||||
-H "Authorization: token ${MOKOGIT_TOKEN}" \
|
||||
"${API}/labels" 2>/dev/null \
|
||||
| grep -oP "\"id\":\s*\K[0-9]+(?=[^}]*\"name\":\s*\"${LABEL_NAME}\")" \
|
||||
| head -1 || true)
|
||||
|
||||
if [[ -n "$LABEL_ID" ]]; then
|
||||
curl -sf -X POST \
|
||||
-H "Authorization: token ${MOKOGITEA_TOKEN}" \
|
||||
-H "Authorization: token ${MOKOGIT_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API}/issues/${ISSUE_NUM}/labels" \
|
||||
-d "{\"labels\":[${LABEL_ID}]}" \
|
||||
|
||||
@@ -24,7 +24,7 @@ use MokoCli\CliFramework;
|
||||
|
||||
class ClientDashboardCli extends CliFramework
|
||||
{
|
||||
private string $giteaUrl = 'https://git.mokoconsulting.tech';
|
||||
private string $gitUrl = 'https://git.mokoconsulting.tech';
|
||||
private string $token = '';
|
||||
private string $org = 'MokoConsulting';
|
||||
private string $outputFile = '';
|
||||
@@ -36,8 +36,8 @@ class ClientDashboardCli extends CliFramework
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setDescription('Generate unified client dashboard HTML');
|
||||
$this->addArgument('--token', 'Gitea token (or MOKOGITEA_TOKEN)', '');
|
||||
$this->addArgument('--gitea-url', 'Gitea URL', 'https://git.mokoconsulting.tech');
|
||||
$this->addArgument('--token', 'Git token (or MOKOGIT_TOKEN)', '');
|
||||
$this->addArgument('--git-url', 'Git URL', 'https://git.mokoconsulting.tech');
|
||||
$this->addArgument('--org', 'Primary org (default: MokoConsulting)', 'MokoConsulting');
|
||||
$this->addArgument('--output', 'Output HTML file (default: stdout)', '');
|
||||
$this->addArgument('-o', 'Output HTML file (alias)', '');
|
||||
@@ -48,7 +48,7 @@ class ClientDashboardCli extends CliFramework
|
||||
|
||||
protected function run(): int
|
||||
{
|
||||
$this->giteaUrl = rtrim($this->getArgument('--gitea-url'), '/');
|
||||
$this->gitUrl = rtrim($this->getArgument('--git-url'), '/');
|
||||
$this->token = $this->getArgument('--token');
|
||||
$this->org = $this->getArgument('--org');
|
||||
$this->outputFile = $this->getArgument('--output') ?: $this->getArgument('-o');
|
||||
@@ -57,11 +57,11 @@ class ClientDashboardCli extends CliFramework
|
||||
$this->sslWarnDays = (int) $this->getArgument('--ssl-warn-days');
|
||||
|
||||
if ($this->token === '') {
|
||||
$this->token = getenv('MOKOGITEA_TOKEN') ?: '';
|
||||
$this->token = getenv('MOKOGIT_TOKEN') ?: '';
|
||||
}
|
||||
|
||||
if ($this->token === '') {
|
||||
$this->log('ERROR', '--token or MOKOGITEA_TOKEN required.');
|
||||
$this->log('ERROR', '--token or MOKOGIT_TOKEN required.');
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -460,7 +460,7 @@ CARD;
|
||||
/** @return array{code: int, body: string} */
|
||||
private function api(string $method, string $endpoint): array
|
||||
{
|
||||
$url = $this->giteaUrl . $endpoint;
|
||||
$url = $this->gitUrl . $endpoint;
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
@@ -24,21 +24,21 @@ use MokoCli\CliFramework;
|
||||
|
||||
class ClientInventoryCli extends CliFramework
|
||||
{
|
||||
private string $giteaUrl = 'https://git.mokoconsulting.tech';
|
||||
private string $gitUrl = 'https://git.mokoconsulting.tech';
|
||||
private string $token = '';
|
||||
private bool $jsonOutput = false;
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setDescription('Discover and list all client-waas repos with their server configuration status');
|
||||
$this->addArgument('--gitea-url', 'Gitea URL (default: https://git.mokoconsulting.tech)', 'https://git.mokoconsulting.tech');
|
||||
$this->addArgument('--token', 'Gitea API token', '');
|
||||
$this->addArgument('--git-url', 'Git URL (default: https://git.mokoconsulting.tech)', 'https://git.mokoconsulting.tech');
|
||||
$this->addArgument('--token', 'Git API token', '');
|
||||
$this->addArgument('--json', 'Output results as JSON', false);
|
||||
}
|
||||
|
||||
protected function run(): int
|
||||
{
|
||||
$this->giteaUrl = rtrim($this->getArgument('--gitea-url'), '/');
|
||||
$this->gitUrl = rtrim($this->getArgument('--git-url'), '/');
|
||||
$this->token = $this->getArgument('--token');
|
||||
$this->jsonOutput = (bool) $this->getArgument('--json');
|
||||
|
||||
@@ -47,7 +47,7 @@ class ClientInventoryCli extends CliFramework
|
||||
return 1;
|
||||
}
|
||||
|
||||
$this->log('INFO', "Scanning Gitea instance: {$this->giteaUrl}");
|
||||
$this->log('INFO', "Scanning Git instance: {$this->gitUrl}");
|
||||
|
||||
// Step 1: List all orgs
|
||||
$orgs = $this->fetchOrgs();
|
||||
@@ -241,7 +241,7 @@ class ClientInventoryCli extends CliFramework
|
||||
|
||||
private function apiRequest(string $method, string $endpoint, ?string $body = null): array
|
||||
{
|
||||
$url = $this->giteaUrl . $endpoint;
|
||||
$url = $this->gitUrl . $endpoint;
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
|
||||
+18
-18
@@ -24,8 +24,8 @@ use MokoCli\CliFramework;
|
||||
|
||||
class ClientProvisionCli extends CliFramework
|
||||
{
|
||||
private string $giteaUrl = 'https://git.mokoconsulting.tech';
|
||||
private string $giteaToken = '';
|
||||
private string $gitUrl = 'https://git.mokoconsulting.tech';
|
||||
private string $gitToken = '';
|
||||
private string $grafanaUrl = '';
|
||||
private string $grafanaToken = '';
|
||||
private string $configFile = '';
|
||||
@@ -65,17 +65,17 @@ class ClientProvisionCli extends CliFramework
|
||||
return 1;
|
||||
}
|
||||
|
||||
$this->giteaToken = $this->config['gitea_token']
|
||||
?? getenv('MOKOGITEA_TOKEN') ?: '';
|
||||
$this->gitToken = $this->config['git_token']
|
||||
?? getenv('MOKOGIT_TOKEN') ?: '';
|
||||
$this->grafanaUrl = $this->config['grafana_url']
|
||||
?? getenv('GRAFANA_URL') ?: '';
|
||||
$this->grafanaToken = $this->config['grafana_token']
|
||||
?? getenv('GRAFANA_TOKEN') ?: '';
|
||||
$this->giteaUrl = $this->config['gitea_url']
|
||||
?? $this->giteaUrl;
|
||||
$this->gitUrl = $this->config['git_url']
|
||||
?? $this->gitUrl;
|
||||
|
||||
if ($this->giteaToken === '') {
|
||||
$this->log('ERROR', 'gitea_token or MOKOGITEA_TOKEN required.');
|
||||
if ($this->gitToken === '') {
|
||||
$this->log('ERROR', 'git_token or MOKOGIT_TOKEN required.');
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ class ClientProvisionCli extends CliFramework
|
||||
{
|
||||
$this->log('INFO', '[1/5] Creating repository...');
|
||||
|
||||
$check = $this->giteaApi(
|
||||
$check = $this->gitApi(
|
||||
'GET',
|
||||
"/api/v1/repos/{$this->org}/{$this->repoName}"
|
||||
);
|
||||
@@ -153,7 +153,7 @@ class ClientProvisionCli extends CliFramework
|
||||
'labels' => true,
|
||||
]);
|
||||
|
||||
$resp = $this->giteaApi(
|
||||
$resp = $this->gitApi(
|
||||
'POST',
|
||||
'/api/v1/repos/MokoConsulting/'
|
||||
. 'Template-Client/generate',
|
||||
@@ -167,7 +167,7 @@ class ClientProvisionCli extends CliFramework
|
||||
|
||||
$this->log('INFO', ' OK: Repo created');
|
||||
|
||||
$this->giteaApi(
|
||||
$this->gitApi(
|
||||
'POST',
|
||||
"/api/v1/repos/{$this->org}/{$this->repoName}/branches",
|
||||
json_encode([
|
||||
@@ -250,7 +250,7 @@ class ClientProvisionCli extends CliFramework
|
||||
continue;
|
||||
}
|
||||
|
||||
$resp = $this->giteaApi(
|
||||
$resp = $this->gitApi(
|
||||
'PUT',
|
||||
"{$api}/{$name}",
|
||||
json_encode(['data' => $value])
|
||||
@@ -391,7 +391,7 @@ class ClientProvisionCli extends CliFramework
|
||||
echo "\n";
|
||||
$this->log('INFO', '[5/5] Provisioning summary');
|
||||
echo str_repeat('=', 60) . "\n";
|
||||
echo " Repo: {$this->giteaUrl}/{$this->org}/{$this->repoName}\n";
|
||||
echo " Repo: {$this->gitUrl}/{$this->org}/{$this->repoName}\n";
|
||||
echo ' Variables: ' . count($vars) . " set\n";
|
||||
echo ' Secrets: ' . count($secrets) . " set\n";
|
||||
echo "\n";
|
||||
@@ -409,14 +409,14 @@ class ClientProvisionCli extends CliFramework
|
||||
string $name,
|
||||
string $value
|
||||
): bool {
|
||||
$resp = $this->giteaApi(
|
||||
$resp = $this->gitApi(
|
||||
'PUT',
|
||||
"{$api}/{$name}",
|
||||
json_encode(['value' => $value])
|
||||
);
|
||||
|
||||
if ($resp['code'] === 404) {
|
||||
$resp = $this->giteaApi(
|
||||
$resp = $this->gitApi(
|
||||
'POST',
|
||||
$api,
|
||||
json_encode(['name' => $name, 'value' => $value])
|
||||
@@ -426,15 +426,15 @@ class ClientProvisionCli extends CliFramework
|
||||
return $resp['code'] >= 200 && $resp['code'] < 300;
|
||||
}
|
||||
|
||||
private function giteaApi(
|
||||
private function gitApi(
|
||||
string $method,
|
||||
string $endpoint,
|
||||
?string $body = null
|
||||
): array {
|
||||
return $this->httpRequest(
|
||||
$this->giteaUrl . $endpoint,
|
||||
$this->gitUrl . $endpoint,
|
||||
$method,
|
||||
"token {$this->giteaToken}",
|
||||
"token {$this->gitToken}",
|
||||
$body
|
||||
);
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ class CreateProjectCli extends CliFramework
|
||||
}
|
||||
|
||||
$config = \MokoCli\Config::load();
|
||||
$platformName = $config->getString('platform', 'gitea');
|
||||
$platformName = $config->getString('platform', 'git');
|
||||
try {
|
||||
$adapter = \MokoCli\PlatformAdapterFactory::create($config);
|
||||
$api = $adapter->getApiClient();
|
||||
@@ -89,8 +89,8 @@ class CreateProjectCli extends CliFramework
|
||||
$this->log('ERROR', "Platform initialization failed: " . $e->getMessage());
|
||||
return 1;
|
||||
}
|
||||
$token = $platformName === 'gitea'
|
||||
? $config->getString('gitea.token', '')
|
||||
$token = $platformName === 'git'
|
||||
? $config->getString('git.token', '')
|
||||
: $config->getString('github.token', '');
|
||||
|
||||
$repoRoot = dirname(__DIR__, 2);
|
||||
@@ -173,7 +173,7 @@ class CreateProjectCli extends CliFramework
|
||||
return $failed > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
private function graphql(string $query, array $variables, string $token, string $platformName = 'gitea'): array
|
||||
private function graphql(string $query, array $variables, string $token, string $platformName = 'git'): array
|
||||
{
|
||||
if ($platformName !== 'github') {
|
||||
return [];
|
||||
@@ -223,7 +223,7 @@ class CreateProjectCli extends CliFramework
|
||||
|
||||
private function detectRepoPlatform(string $org, string $repo, string $token, ?\MokoCli\ApiClient $apiClient = null): string
|
||||
{
|
||||
foreach (['.github/.mokostandards', '.mokogitea/.mokostandards', '.mokostandards'] as $path) {
|
||||
foreach (['.github/.mokostandards', '.mokogit/.mokostandards', '.mokostandards'] as $path) {
|
||||
$data = $this->restGet("repos/{$org}/{$repo}/contents/{$path}", $token, $apiClient);
|
||||
if (!empty($data['content'])) {
|
||||
$content = base64_decode($data['content']);
|
||||
|
||||
+4
-4
@@ -116,14 +116,14 @@ class CreateRepoCli extends CliFramework
|
||||
echo " (dry-run) would set topics: " . implode(', ', $topics) . "\n";
|
||||
}
|
||||
|
||||
echo "Step 3: Creating .mokogitea/manifest.xml...\n";
|
||||
echo "Step 3: Creating .mokogit/manifest.xml...\n";
|
||||
$mokoContent = "platform: {$platform}\nversion: 04.02.30\nmanaged: true\n";
|
||||
if (!$this->dryRun) {
|
||||
try {
|
||||
$adapter->createOrUpdateFile(
|
||||
$org,
|
||||
$name,
|
||||
'.mokogitea/manifest.xml',
|
||||
'.mokogit/manifest.xml',
|
||||
$mokoContent,
|
||||
'chore: add manifest.xml platform config [skip ci]'
|
||||
);
|
||||
@@ -132,11 +132,11 @@ class CreateRepoCli extends CliFramework
|
||||
echo " Warning: " . $e->getMessage() . "\n";
|
||||
}
|
||||
} else {
|
||||
echo " (dry-run) would create .mokogitea/manifest.xml\n";
|
||||
echo " (dry-run) would create .mokogit/manifest.xml\n";
|
||||
}
|
||||
|
||||
echo "Step 4: Creating README.md...\n";
|
||||
$baseUrl = $platformName === 'gitea' ? $config->getString('gitea.url', 'https://git.mokoconsulting.tech') : 'https://github.com';
|
||||
$baseUrl = $platformName === 'git' ? $config->getString('git.url', 'https://git.mokoconsulting.tech') : 'https://github.com';
|
||||
$repoUrl = "{$baseUrl}/{$org}/{$name}";
|
||||
$standardsUrl = "{$baseUrl}/{$org}/MokoCli";
|
||||
$readmeContent = "<!--\n"
|
||||
|
||||
@@ -833,7 +833,7 @@ class DeployJoomla extends CliFramework
|
||||
/**
|
||||
* Resolve source directory with smart fallback chain:
|
||||
* 1. --src-dir flag (explicit)
|
||||
* 2. .mokogitea/manifest.xml <deploy><source-dir>
|
||||
* 2. .mokogit/manifest.xml <deploy><source-dir>
|
||||
* 3. src/ directory
|
||||
* 4. htdocs/ directory
|
||||
* 5. Repo root (for flat-layout extensions)
|
||||
@@ -851,8 +851,8 @@ class DeployJoomla extends CliFramework
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// 2. Read from .mokogitea/manifest.xml
|
||||
$mokoManifest = "{$repoPath}/.mokogitea/manifest.xml";
|
||||
// 2. Read from .mokogit/manifest.xml
|
||||
$mokoManifest = "{$repoPath}/.mokogit/manifest.xml";
|
||||
if (file_exists($mokoManifest)) {
|
||||
$xml = @simplexml_load_file($mokoManifest);
|
||||
if ($xml !== false) {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/dev_branch_reset.php
|
||||
* BRIEF: Delete and recreate dev branch from main via Gitea API
|
||||
* BRIEF: Delete and recreate dev branch from main via Git API
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
@@ -23,9 +23,9 @@ class DevBranchResetCli extends CliFramework
|
||||
{
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setDescription('Delete and recreate dev branch from main via Gitea API');
|
||||
$this->addArgument('--token', 'Gitea API token', '');
|
||||
$this->addArgument('--api-base', 'Gitea API base URL', '');
|
||||
$this->setDescription('Delete and recreate dev branch from main via Git API');
|
||||
$this->addArgument('--token', 'Git API token', '');
|
||||
$this->addArgument('--api-base', 'Git API base URL', '');
|
||||
$this->addArgument('--branch', 'Branch to reset', 'dev');
|
||||
$this->addArgument('--from', 'Source branch', 'main');
|
||||
$this->addArgument('--output-summary', 'Write to $GITHUB_STEP_SUMMARY', false);
|
||||
@@ -33,7 +33,7 @@ class DevBranchResetCli extends CliFramework
|
||||
|
||||
protected function run(): int
|
||||
{
|
||||
$token = $this->getArgument('--token') ?: getenv('MOKOGITEA_TOKEN') ?: getenv('GITEA_TOKEN') ?: '';
|
||||
$token = $this->getArgument('--token') ?: getenv('MOKOGIT_TOKEN') ?: getenv('GIT_TOKEN') ?: '';
|
||||
$apiBase = $this->getArgument('--api-base');
|
||||
$branch = $this->getArgument('--branch');
|
||||
$from = $this->getArgument('--from');
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/joomla_metadata_validate.php
|
||||
* VERSION: 09.43.00
|
||||
* BRIEF: Validate MokoGitea repo metadata against Joomla extension manifest XML
|
||||
* BRIEF: Validate MokoGit repo metadata against Joomla extension manifest XML
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
@@ -22,7 +22,7 @@ use MokoCli\CliFramework;
|
||||
|
||||
class JoomlaMetadataValidateCli extends CliFramework
|
||||
{
|
||||
/** Joomla element prefix map — must match MokoGitea's cleanJoomlaElement() */
|
||||
/** Joomla element prefix map — must match MokoGit's cleanJoomlaElement() */
|
||||
private const JOOMLA_PREFIX = [
|
||||
'package' => 'pkg_',
|
||||
'component' => 'com_',
|
||||
@@ -34,12 +34,12 @@ class JoomlaMetadataValidateCli extends CliFramework
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setDescription('Validate MokoGitea repo metadata against Joomla extension manifest XML');
|
||||
$this->setDescription('Validate MokoGit repo metadata against Joomla extension manifest XML');
|
||||
$this->addArgument('--path', 'Repo root path (default: current directory)', '.');
|
||||
$this->addArgument('--token', 'Gitea API token (or GITEA_TOKEN env)', '');
|
||||
$this->addArgument('--org', 'Gitea org', 'MokoConsulting');
|
||||
$this->addArgument('--token', 'Git API token (or GIT_TOKEN env)', '');
|
||||
$this->addArgument('--org', 'Git org', 'MokoConsulting');
|
||||
$this->addArgument('--repo', 'Repo name (auto-detected from git if empty)', '');
|
||||
$this->addArgument('--api-base', 'Gitea API base URL', 'https://git.mokoconsulting.tech/api/v1');
|
||||
$this->addArgument('--api-base', 'Git API base URL', 'https://git.mokoconsulting.tech/api/v1');
|
||||
$this->addArgument('--ci', 'CI mode: exit 1 on any error', false);
|
||||
$this->addArgument('--json', 'Output as JSON', false);
|
||||
}
|
||||
@@ -47,7 +47,7 @@ class JoomlaMetadataValidateCli extends CliFramework
|
||||
protected function run(): int
|
||||
{
|
||||
$path = realpath($this->getArgument('--path')) ?: $this->getArgument('--path');
|
||||
$token = $this->getArgument('--token') ?: getenv('GITEA_TOKEN') ?: '';
|
||||
$token = $this->getArgument('--token') ?: getenv('GIT_TOKEN') ?: '';
|
||||
$org = $this->getArgument('--org');
|
||||
$repoName = $this->getArgument('--repo');
|
||||
$apiBase = rtrim($this->getArgument('--api-base'), '/');
|
||||
@@ -73,11 +73,11 @@ class JoomlaMetadataValidateCli extends CliFramework
|
||||
|
||||
$this->log('INFO', "Joomla manifest: {$joomlaXml['path']}");
|
||||
|
||||
// ── Step 2: Load MokoGitea metadata ─────────────────────────
|
||||
// ── Step 2: Load MokoGit metadata ─────────────────────────
|
||||
$metadata = $this->loadMetadata($path, $org, $repoName, $token, $apiBase);
|
||||
|
||||
if ($metadata === null) {
|
||||
$this->log('ERROR', 'Could not load MokoGitea metadata');
|
||||
$this->log('ERROR', 'Could not load MokoGit metadata');
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ class JoomlaMetadataValidateCli extends CliFramework
|
||||
private function loadMetadata(string $root, string $org, string $repoName, string $token, string $apiBase): ?array
|
||||
{
|
||||
if ($token === '') {
|
||||
$this->log('ERROR', 'No API token provided (use --token or set GITEA_TOKEN env var)');
|
||||
$this->log('ERROR', 'No API token provided (use --token or set GIT_TOKEN env var)');
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -202,7 +202,7 @@ class JoomlaMetadataValidateCli extends CliFramework
|
||||
|
||||
if ($httpCode === 404) {
|
||||
$this->log('ERROR', "API endpoint not found: {$url}");
|
||||
$this->log('ERROR', 'Server may need MokoGitea-Fork >= #650 (metadata endpoint rename)');
|
||||
$this->log('ERROR', 'Server may need MokoGit-Fork >= #650 (metadata endpoint rename)');
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -328,7 +328,7 @@ class JoomlaMetadataValidateCli extends CliFramework
|
||||
// =================================================================
|
||||
|
||||
/**
|
||||
* Normalize extension_type — map MokoGitea types to Joomla types.
|
||||
* Normalize extension_type — map MokoGit types to Joomla types.
|
||||
*/
|
||||
private function normalizeExtensionType(string $type): string
|
||||
{
|
||||
@@ -340,7 +340,7 @@ class JoomlaMetadataValidateCli extends CliFramework
|
||||
|
||||
/**
|
||||
* Derive the Joomla element name from type + name.
|
||||
* Replicates MokoGitea's cleanJoomlaElement() + prefix logic.
|
||||
* Replicates MokoGit's cleanJoomlaElement() + prefix logic.
|
||||
*/
|
||||
private function deriveElement(string $type, string $name): string
|
||||
{
|
||||
|
||||
@@ -30,7 +30,7 @@ use MokoCli\{ApiClient, AuditLogger, CliFramework, Config, PlatformAdapterFactor
|
||||
/**
|
||||
* Joomla Release Manager
|
||||
*
|
||||
* Creates and manages Joomla extension releases on Gitea, including
|
||||
* Creates and manages Joomla extension releases on Git, including
|
||||
* package building, asset upload, and update stream management.
|
||||
*
|
||||
* @since 04.06.00
|
||||
@@ -425,9 +425,9 @@ class JoomlaRelease extends CliFramework
|
||||
}
|
||||
|
||||
$releaseConfig = Config::load();
|
||||
$releasePlatform = $releaseConfig->getString('platform', 'gitea');
|
||||
$releaseToken = $releasePlatform === 'gitea'
|
||||
? $releaseConfig->getString('gitea.token', '')
|
||||
$releasePlatform = $releaseConfig->getString('platform', 'git');
|
||||
$releaseToken = $releasePlatform === 'git'
|
||||
? $releaseConfig->getString('git.token', '')
|
||||
: $releaseConfig->getString('github.token', '');
|
||||
$acceptHeader = $releasePlatform === 'github' ? 'application/vnd.github+json' : 'application/json';
|
||||
$ch = curl_init();
|
||||
@@ -512,12 +512,12 @@ class JoomlaRelease extends CliFramework
|
||||
$this->rmdir($tmpDir);
|
||||
}
|
||||
$config = Config::load();
|
||||
$platform = $config->getString('platform', 'gitea');
|
||||
$token = $platform === 'gitea'
|
||||
? $config->getString('gitea.token', '')
|
||||
$platform = $config->getString('platform', 'git');
|
||||
$token = $platform === 'git'
|
||||
? $config->getString('git.token', '')
|
||||
: $config->getString('github.token', '');
|
||||
$cloneHost = $platform === 'gitea'
|
||||
? rtrim($config->getString('gitea.url', 'https://git.mokoconsulting.tech'), '/')
|
||||
$cloneHost = $platform === 'git'
|
||||
? rtrim($config->getString('git.url', 'https://git.mokoconsulting.tech'), '/')
|
||||
: 'https://github.com';
|
||||
$url = "https://x-access-token:{$token}@" . preg_replace('#^https?://#', '', $cloneHost) . '/' . self::ORG . "/{$repo}.git";
|
||||
$cmd = ['git', 'clone', '--depth', '1', '--quiet', $url, $tmpDir];
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/license_manage.php
|
||||
* BRIEF: Manage license packages and keys via MokoGitea licensing API
|
||||
* BRIEF: Manage license packages and keys via MokoGit licensing API
|
||||
*
|
||||
* Usage:
|
||||
* php bin/moko license:list --org MokoConsulting
|
||||
@@ -38,9 +38,9 @@ class LicenseManage extends CliFramework
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setDescription('Manage license packages and keys via MokoGitea licensing API');
|
||||
$this->setDescription('Manage license packages and keys via MokoGit licensing API');
|
||||
$this->addArgument('--org', 'Organization name', '');
|
||||
$this->addArgument('--api-base', 'Gitea API base URL', '');
|
||||
$this->addArgument('--api-base', 'Git API base URL', '');
|
||||
$this->addArgument('--token', 'API token (or set GH_TOKEN env)', '');
|
||||
|
||||
// Package args
|
||||
@@ -71,7 +71,7 @@ class LicenseManage extends CliFramework
|
||||
{
|
||||
// Resolve API base
|
||||
$this->apiBase = $this->getArgument('--api-base')
|
||||
?: getenv('GITEA_URL')
|
||||
?: getenv('GIT_URL')
|
||||
?: 'https://git.mokoconsulting.tech';
|
||||
$this->apiBase = rtrim($this->apiBase, '/');
|
||||
|
||||
@@ -657,7 +657,7 @@ HELP;
|
||||
|
||||
if ($httpCode === 404) {
|
||||
$this->log("API endpoint not found: {$path}", 'ERROR');
|
||||
$this->log('The licensing API may not be deployed yet. Check MokoGitea version.', 'WARN');
|
||||
$this->log('The licensing API may not be deployed yet. Check MokoGit version.', 'WARN');
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,10 +29,10 @@ class ManifestDetectCli extends CliFramework
|
||||
$this->addArgument('--json', 'Output as JSON', false);
|
||||
$this->addArgument('--diff', 'Show diff against current manifest API values', false);
|
||||
$this->addArgument('--update', 'Push detected fields to manifest API', false);
|
||||
$this->addArgument('--token', 'Gitea API token (or GITEA_TOKEN env)', '');
|
||||
$this->addArgument('--api-base', 'Gitea API base URL', 'https://git.mokoconsulting.tech/api/v1');
|
||||
$this->addArgument('--org', 'Gitea org', 'MokoConsulting');
|
||||
$this->addArgument('--repo', 'Gitea repo name (auto-detected from remote if empty)', '');
|
||||
$this->addArgument('--token', 'Git API token (or GIT_TOKEN env)', '');
|
||||
$this->addArgument('--api-base', 'Git API base URL', 'https://git.mokoconsulting.tech/api/v1');
|
||||
$this->addArgument('--org', 'Git org', 'MokoConsulting');
|
||||
$this->addArgument('--repo', 'Git repo name (auto-detected from remote if empty)', '');
|
||||
$this->addArgument('--github-output', 'Append fields to $GITHUB_OUTPUT', false);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ class ManifestDetectCli extends CliFramework
|
||||
$diffMode = (bool) $this->getArgument('--diff');
|
||||
$updateMode = (bool) $this->getArgument('--update');
|
||||
$ghOutput = (bool) $this->getArgument('--github-output');
|
||||
$token = $this->getArgument('--token') ?: getenv('GITEA_TOKEN') ?: '';
|
||||
$token = $this->getArgument('--token') ?: getenv('GIT_TOKEN') ?: '';
|
||||
$apiBase = rtrim($this->getArgument('--api-base'), '/');
|
||||
$org = $this->getArgument('--org');
|
||||
$repoName = $this->getArgument('--repo');
|
||||
@@ -74,7 +74,7 @@ class ManifestDetectCli extends CliFramework
|
||||
// ── Output ──────────────────────────────────────────────────
|
||||
if ($diffMode || $updateMode) {
|
||||
if ($token === '') {
|
||||
$this->log('ERROR', 'API token required for --diff/--update (use --token or GITEA_TOKEN env)');
|
||||
$this->log('ERROR', 'API token required for --diff/--update (use --token or GIT_TOKEN env)');
|
||||
return 1;
|
||||
}
|
||||
if ($repoName === '') {
|
||||
|
||||
@@ -40,7 +40,7 @@ class ManifestElementCli extends CliFramework
|
||||
$githubOutput = (bool) $this->getArgument('--github-output');
|
||||
$root = realpath($path) ?: $path;
|
||||
$platform = 'generic';
|
||||
$manifestXml = "{$root}/.mokogitea/manifest.xml";
|
||||
$manifestXml = "{$root}/.mokogit/manifest.xml";
|
||||
if (file_exists($manifestXml)) {
|
||||
$content = file_get_contents($manifestXml);
|
||||
if (preg_match('/<platform>([^<]+)<\/platform>/', $content, $pm)) {
|
||||
|
||||
@@ -26,10 +26,10 @@ class ManifestIntegrityCli extends CliFramework
|
||||
{
|
||||
$this->setDescription('Cross-check manifest fields against repo contents across the org');
|
||||
$this->addArgument('--path', 'Single repo path (local mode)', '');
|
||||
$this->addArgument('--org', 'Gitea org (bulk mode)', 'MokoConsulting');
|
||||
$this->addArgument('--org', 'Git org (bulk mode)', 'MokoConsulting');
|
||||
$this->addArgument('--repo', 'Single repo name (remote mode)', '');
|
||||
$this->addArgument('--token', 'Gitea API token (or GITEA_TOKEN env)', '');
|
||||
$this->addArgument('--api-base', 'Gitea API base URL', 'https://git.mokoconsulting.tech/api/v1');
|
||||
$this->addArgument('--token', 'Git API token (or GIT_TOKEN env)', '');
|
||||
$this->addArgument('--api-base', 'Git API base URL', 'https://git.mokoconsulting.tech/api/v1');
|
||||
$this->addArgument('--fix', 'Push fixes for detected drift', false);
|
||||
$this->addArgument('--json', 'Output as JSON', false);
|
||||
$this->addArgument('--quiet', 'Only show repos with issues', false);
|
||||
@@ -40,14 +40,14 @@ class ManifestIntegrityCli extends CliFramework
|
||||
$path = $this->getArgument('--path');
|
||||
$org = $this->getArgument('--org');
|
||||
$repoName = $this->getArgument('--repo');
|
||||
$token = $this->getArgument('--token') ?: getenv('GITEA_TOKEN') ?: '';
|
||||
$token = $this->getArgument('--token') ?: getenv('GIT_TOKEN') ?: '';
|
||||
$apiBase = rtrim($this->getArgument('--api-base'), '/');
|
||||
$fixMode = (bool) $this->getArgument('--fix');
|
||||
$jsonMode = (bool) $this->getArgument('--json');
|
||||
$quiet = (bool) $this->getArgument('--quiet');
|
||||
|
||||
if ($token === '') {
|
||||
$this->log('ERROR', 'API token required (use --token or GITEA_TOKEN env)');
|
||||
$this->log('ERROR', 'API token required (use --token or GIT_TOKEN env)');
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ require_once __DIR__ . '/../lib/Enterprise/CliFramework.php';
|
||||
use MokoCli\{CliFramework, SourceResolver};
|
||||
|
||||
/**
|
||||
* Reads the <licensing> block from .mokogitea/manifest.xml and ensures that the
|
||||
* Reads the <licensing> block from .mokogit/manifest.xml and ensures that the
|
||||
* Joomla extension manifest contains the correct <updateservers> and <dlid> tags.
|
||||
*
|
||||
* manifest.xml licensing block example:
|
||||
@@ -53,7 +53,7 @@ class ManifestLicensingCli extends CliFramework
|
||||
$ghOutput = (bool) $this->getArgument('--github-output');
|
||||
|
||||
// ── 1. Read manifest.xml ──────────────────────────────────────────
|
||||
$manifestFile = "{$root}/.mokogitea/manifest.xml";
|
||||
$manifestFile = "{$root}/.mokogit/manifest.xml";
|
||||
|
||||
if (!file_exists($manifestFile)) {
|
||||
$this->log('WARN', "No manifest.xml found at {$manifestFile}");
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/manifest_read.php
|
||||
* VERSION: 09.43.00
|
||||
* BRIEF: Read repo metadata from Gitea manifest API, auto-detect the rest
|
||||
* BRIEF: Read repo metadata from Git manifest API, auto-detect the rest
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
@@ -27,7 +27,7 @@ class ManifestReadCli extends CliFramework
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setDescription('Read repo metadata from Gitea API with auto-detection fallback');
|
||||
$this->setDescription('Read repo metadata from Git API with auto-detection fallback');
|
||||
$this->addArgument('--path', 'Repository root path', '.');
|
||||
$this->addArgument('--field', 'Single field name to output', '');
|
||||
$this->addArgument('--all', 'Print all fields as KEY=VALUE lines', false);
|
||||
@@ -55,7 +55,7 @@ class ManifestReadCli extends CliFramework
|
||||
// ── 1. Resolve org/repo ──────────────────────────────────────────
|
||||
[$org, $repo] = $this->resolveOrgRepo($root);
|
||||
|
||||
// ── 2. Primary: Gitea manifest API ───────────────────────────────
|
||||
// ── 2. Primary: Git manifest API ───────────────────────────────
|
||||
$fields = null;
|
||||
if ($org !== '' && $repo !== '') {
|
||||
$fields = $this->fetchFromApi($org, $repo);
|
||||
@@ -82,12 +82,12 @@ class ManifestReadCli extends CliFramework
|
||||
return $this->outputFields($fields, $mode, $field);
|
||||
}
|
||||
|
||||
// ── Gitea manifest API ───────────────────────────────────────────────
|
||||
// ── Git manifest API ───────────────────────────────────────────────
|
||||
|
||||
private function fetchFromApi(string $org, string $repo): ?array
|
||||
{
|
||||
$token = getenv('GA_TOKEN') ?: getenv('GITEA_TOKEN') ?: '';
|
||||
$baseUrl = getenv('GITEA_URL') ?: 'https://git.mokoconsulting.tech';
|
||||
$token = getenv('GA_TOKEN') ?: getenv('GIT_TOKEN') ?: '';
|
||||
$baseUrl = getenv('GIT_URL') ?: 'https://git.mokoconsulting.tech';
|
||||
$baseUrl = rtrim($baseUrl, '/');
|
||||
|
||||
if ($token === '') {
|
||||
@@ -123,7 +123,7 @@ class ManifestReadCli extends CliFramework
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->log('INFO', "Loaded metadata from Gitea manifest API ({$org}/{$repo})");
|
||||
$this->log('INFO', "Loaded metadata from Git manifest API ({$org}/{$repo})");
|
||||
return $data;
|
||||
}
|
||||
|
||||
@@ -370,7 +370,7 @@ class ManifestReadCli extends CliFramework
|
||||
*/
|
||||
private function resolveOrgRepo(string $root): array
|
||||
{
|
||||
// 1. GITHUB_REPOSITORY env (set in Gitea Actions / GitHub Actions)
|
||||
// 1. GITHUB_REPOSITORY env (set in Git Actions / GitHub Actions)
|
||||
$envRepo = getenv('GITHUB_REPOSITORY') ?: '';
|
||||
if ($envRepo !== '' && str_contains($envRepo, '/')) {
|
||||
return explode('/', $envRepo, 2);
|
||||
@@ -447,7 +447,7 @@ class ManifestReadCli extends CliFramework
|
||||
break;
|
||||
|
||||
case 'github-output':
|
||||
$outputFile = getenv('GITHUB_OUTPUT') ?: getenv('GITEA_OUTPUT') ?: '';
|
||||
$outputFile = getenv('GITHUB_OUTPUT') ?: getenv('GIT_OUTPUT') ?: '';
|
||||
$lines = [];
|
||||
foreach ($fields as $k => $v) {
|
||||
$envKey = str_replace('-', '_', $k);
|
||||
|
||||
@@ -26,8 +26,8 @@ class PlatformDetectCli extends CliFramework
|
||||
{
|
||||
$this->setDescription('Auto-detect repository platform type and optionally update manifest');
|
||||
$this->addArgument('--path', 'Local repo path to scan (default: .)', '.');
|
||||
$this->addArgument('--token', 'Gitea API token for updating manifest', '');
|
||||
$this->addArgument('--gitea-url', 'Gitea URL (default: https://git.mokoconsulting.tech)', 'https://git.mokoconsulting.tech');
|
||||
$this->addArgument('--token', 'Git API token for updating manifest', '');
|
||||
$this->addArgument('--git-url', 'Git URL (default: https://git.mokoconsulting.tech)', 'https://git.mokoconsulting.tech');
|
||||
$this->addArgument('--owner', 'Repo owner for API update', '');
|
||||
$this->addArgument('--repo', 'Repo name for API update', '');
|
||||
$this->addArgument('--update', 'Update manifest.platform via API (flag)', 'false');
|
||||
@@ -40,7 +40,7 @@ class PlatformDetectCli extends CliFramework
|
||||
$root = realpath($path) ?: $path;
|
||||
|
||||
$token = $this->getArgument('--token');
|
||||
$giteaUrl = rtrim($this->getArgument('--gitea-url'), '/');
|
||||
$gitUrl = rtrim($this->getArgument('--git-url'), '/');
|
||||
$owner = $this->getArgument('--owner');
|
||||
$repo = $this->getArgument('--repo');
|
||||
$doUpdate = $this->isFlagSet('--update');
|
||||
@@ -79,7 +79,7 @@ class PlatformDetectCli extends CliFramework
|
||||
$this->log('INFO', "Updating manifest.platform for {$owner}/{$repo} to \"{$platform}\"...");
|
||||
|
||||
$response = $this->apiRequest(
|
||||
$giteaUrl,
|
||||
$gitUrl,
|
||||
$token,
|
||||
'PATCH',
|
||||
"/api/v1/repos/{$owner}/{$repo}/metadata",
|
||||
@@ -136,7 +136,7 @@ class PlatformDetectCli extends CliFramework
|
||||
|
||||
// 5. Platform — is mokocli itself or org-config
|
||||
$repoName = basename($root);
|
||||
if (in_array($repoName, ['mokocli', 'mokogitea-org-config'])) {
|
||||
if (in_array($repoName, ['mokocli', 'mokogit-org-config'])) {
|
||||
return 'platform';
|
||||
}
|
||||
|
||||
@@ -152,13 +152,13 @@ class PlatformDetectCli extends CliFramework
|
||||
}
|
||||
|
||||
private function apiRequest(
|
||||
string $giteaUrl,
|
||||
string $gitUrl,
|
||||
string $token,
|
||||
string $method,
|
||||
string $endpoint,
|
||||
?string $body = null
|
||||
): array {
|
||||
$url = $giteaUrl . $endpoint;
|
||||
$url = $gitUrl . $endpoint;
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
|
||||
+2
-2
@@ -37,8 +37,8 @@ class ReleaseCli extends CliFramework
|
||||
$repoRoot = dirname(__DIR__, 2);
|
||||
$syncFile = "{$repoRoot}/lib/Enterprise/RepositorySynchronizer.php";
|
||||
// Check both workflow directories for the bulk-repo-sync workflow
|
||||
$bulkSyncFile = file_exists("{$repoRoot}/.mokogitea/workflows/bulk-repo-sync.yml")
|
||||
? "{$repoRoot}/.mokogitea/workflows/bulk-repo-sync.yml"
|
||||
$bulkSyncFile = file_exists("{$repoRoot}/.mokogit/workflows/bulk-repo-sync.yml")
|
||||
? "{$repoRoot}/.mokogit/workflows/bulk-repo-sync.yml"
|
||||
: "{$repoRoot}/.github/workflows/bulk-repo-sync.yml";
|
||||
|
||||
// -- Step 1: Read current version --
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/release_body_update.php
|
||||
* BRIEF: Update Gitea release body with changelog extract and checksums
|
||||
* BRIEF: Update Git release body with changelog extract and checksums
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
@@ -23,12 +23,12 @@ class ReleaseBodyUpdateCli extends CliFramework
|
||||
{
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setDescription('Update Gitea release body with changelog extract and checksums');
|
||||
$this->setDescription('Update Git release body with changelog extract and checksums');
|
||||
$this->addArgument('--path', 'Repo root for CHANGELOG.md', '.');
|
||||
$this->addArgument('--version', 'Version string', '');
|
||||
$this->addArgument('--release-tag', 'Gitea release tag', '');
|
||||
$this->addArgument('--token', 'Gitea API token', '');
|
||||
$this->addArgument('--api-base', 'Gitea API base URL', '');
|
||||
$this->addArgument('--release-tag', 'Git release tag', '');
|
||||
$this->addArgument('--token', 'Git API token', '');
|
||||
$this->addArgument('--api-base', 'Git API base URL', '');
|
||||
$this->addArgument('--zip-name', 'ZIP filename for checksum table', '');
|
||||
$this->addArgument('--tar-name', 'tar.gz filename for checksum table', '');
|
||||
$this->addArgument('--zip-sha', 'SHA256 of ZIP', '');
|
||||
@@ -50,7 +50,7 @@ class ReleaseBodyUpdateCli extends CliFramework
|
||||
$outputSummary = $this->getArgument('--output-summary');
|
||||
|
||||
if (empty($token)) {
|
||||
$token = getenv('MOKOGITEA_TOKEN') ?: getenv('GITEA_TOKEN') ?: '';
|
||||
$token = getenv('MOKOGIT_TOKEN') ?: getenv('GIT_TOKEN') ?: '';
|
||||
}
|
||||
|
||||
if (empty($version) || empty($releaseTag) || empty($token) || empty($apiBase)) {
|
||||
|
||||
+11
-11
@@ -40,8 +40,8 @@ class ReleaseCascadeCli extends CliFramework
|
||||
{
|
||||
$this->setDescription('Cascade release zip to all lower stability channels');
|
||||
$this->addArgument('--stability', 'Source stability channel (required)', '');
|
||||
$this->addArgument('--token', 'Gitea API token (required)', '');
|
||||
$this->addArgument('--api-base', 'Gitea API base URL for the repo (required)', '');
|
||||
$this->addArgument('--token', 'Git API token (required)', '');
|
||||
$this->addArgument('--api-base', 'Git API base URL for the repo (required)', '');
|
||||
}
|
||||
|
||||
protected function run(): int
|
||||
@@ -51,9 +51,9 @@ class ReleaseCascadeCli extends CliFramework
|
||||
$apiBase = rtrim($this->getArgument('--api-base'), '/');
|
||||
|
||||
if ($token === '') {
|
||||
$envToken = getenv('MOKOGITEA_TOKEN');
|
||||
$envToken = getenv('MOKOGIT_TOKEN');
|
||||
if ($envToken === false || $envToken === '') {
|
||||
$envToken = getenv('GITEA_TOKEN');
|
||||
$envToken = getenv('GIT_TOKEN');
|
||||
}
|
||||
if ($envToken !== false && $envToken !== '') {
|
||||
$token = $envToken;
|
||||
@@ -85,7 +85,7 @@ class ReleaseCascadeCli extends CliFramework
|
||||
}
|
||||
|
||||
// 1. Get source release
|
||||
$sourceRelease = $this->giteaApi("{$apiBase}/releases/tags/{$sourceTag}", $token);
|
||||
$sourceRelease = $this->gitApi("{$apiBase}/releases/tags/{$sourceTag}", $token);
|
||||
if ($sourceRelease === null) {
|
||||
$this->log('WARN', "No release found at tag '{$sourceTag}' — nothing to cascade.");
|
||||
return 0;
|
||||
@@ -179,7 +179,7 @@ class ReleaseCascadeCli extends CliFramework
|
||||
}
|
||||
|
||||
// Find existing release at target tag
|
||||
$existing = $this->giteaApi("{$apiBase}/releases/tags/{$targetTag}", $token);
|
||||
$existing = $this->gitApi("{$apiBase}/releases/tags/{$targetTag}", $token);
|
||||
|
||||
if ($existing !== null && !empty($existing['id'])) {
|
||||
$releaseId = (int) $existing['id'];
|
||||
@@ -189,7 +189,7 @@ class ReleaseCascadeCli extends CliFramework
|
||||
foreach ($existingAssets as $asset) {
|
||||
$assetId = $asset['id'] ?? 0;
|
||||
if ($assetId > 0) {
|
||||
$this->giteaApi(
|
||||
$this->gitApi(
|
||||
"{$apiBase}/releases/{$releaseId}/assets/{$assetId}",
|
||||
$token, 'DELETE'
|
||||
);
|
||||
@@ -201,7 +201,7 @@ class ReleaseCascadeCli extends CliFramework
|
||||
'name' => $sourceVersion,
|
||||
'body' => $sourceBody,
|
||||
]);
|
||||
$this->giteaApi(
|
||||
$this->gitApi(
|
||||
"{$apiBase}/releases/{$releaseId}",
|
||||
$token, 'PATCH', $updatePayload
|
||||
);
|
||||
@@ -217,7 +217,7 @@ class ReleaseCascadeCli extends CliFramework
|
||||
'body' => $sourceBody,
|
||||
'prerelease' => ($targetTag !== 'stable'),
|
||||
]);
|
||||
$newRelease = $this->giteaApi("{$apiBase}/releases", $token, 'POST', $createPayload);
|
||||
$newRelease = $this->gitApi("{$apiBase}/releases", $token, 'POST', $createPayload);
|
||||
if ($newRelease === null || empty($newRelease['id'])) {
|
||||
$this->log('ERROR', " Failed to create release at tag '{$targetTag}'");
|
||||
return false;
|
||||
@@ -302,9 +302,9 @@ class ReleaseCascadeCli extends CliFramework
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an HTTP request to the Gitea API.
|
||||
* Make an HTTP request to the Git API.
|
||||
*/
|
||||
private function giteaApi(
|
||||
private function gitApi(
|
||||
string $url,
|
||||
string $token,
|
||||
string $method = 'GET',
|
||||
|
||||
+13
-13
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/release_create.php
|
||||
* BRIEF: Create or overwrite a Gitea release with proper naming
|
||||
* BRIEF: Create or overwrite a Git release with proper naming
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
@@ -23,12 +23,12 @@ class ReleaseCreateCli extends CliFramework
|
||||
{
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setDescription('Create or overwrite a Gitea release with proper naming');
|
||||
$this->setDescription('Create or overwrite a Git release with proper naming');
|
||||
$this->addArgument('--path', 'Repo root for manifest detection (default: .)', '.');
|
||||
$this->addArgument('--version', 'Version string (required)', '');
|
||||
$this->addArgument('--tag', 'Release tag name (required)', '');
|
||||
$this->addArgument('--token', 'Gitea API token (required)', '');
|
||||
$this->addArgument('--api-base', 'Gitea API base URL for the repo (required)', '');
|
||||
$this->addArgument('--token', 'Git API token (required)', '');
|
||||
$this->addArgument('--api-base', 'Git API base URL for the repo (required)', '');
|
||||
$this->addArgument('--branch', 'Target commitish (default: main)', 'main');
|
||||
$this->addArgument('--repo', 'Repo name for fallback element detection', '');
|
||||
$this->addArgument('--prerelease', 'Mark release as prerelease', false);
|
||||
@@ -47,9 +47,9 @@ class ReleaseCreateCli extends CliFramework
|
||||
|
||||
// Allow token from environment
|
||||
if ($token === '') {
|
||||
$envToken = getenv('MOKOGITEA_TOKEN');
|
||||
$envToken = getenv('MOKOGIT_TOKEN');
|
||||
if ($envToken === false || $envToken === '') {
|
||||
$envToken = getenv('GITEA_TOKEN');
|
||||
$envToken = getenv('GIT_TOKEN');
|
||||
}
|
||||
if ($envToken !== false && $envToken !== '') {
|
||||
$token = $envToken;
|
||||
@@ -62,7 +62,7 @@ class ReleaseCreateCli extends CliFramework
|
||||
$this->log('ERROR', " --branch main Target commitish (default: main)");
|
||||
$this->log('ERROR', " --repo REPO Repo name for fallback element detection");
|
||||
$this->log('ERROR', " --prerelease Mark release as prerelease");
|
||||
$this->log('ERROR', " Token can also be set via MOKOGITEA_TOKEN or GITEA_TOKEN env var");
|
||||
$this->log('ERROR', " Token can also be set via MOKOGIT_TOKEN or GIT_TOKEN env var");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ class ReleaseCreateCli extends CliFramework
|
||||
// Detect platform and display name from manifest.xml
|
||||
$platform = 'generic';
|
||||
$prettyName = '';
|
||||
$manifestXml = "{$root}/.mokogitea/manifest.xml";
|
||||
$manifestXml = "{$root}/.mokogit/manifest.xml";
|
||||
if (file_exists($manifestXml)) {
|
||||
$content = file_get_contents($manifestXml);
|
||||
if ($content !== false) {
|
||||
@@ -238,16 +238,16 @@ class ReleaseCreateCli extends CliFramework
|
||||
|
||||
// ── Delete existing release at tag (if present) ─────────────────────────────
|
||||
|
||||
$existing = $this->giteaApi("{$apiBase}/releases/tags/{$tag}", $token);
|
||||
$existing = $this->gitApi("{$apiBase}/releases/tags/{$tag}", $token);
|
||||
if ($existing !== null && !empty($existing['id'])) {
|
||||
$existingId = $existing['id'];
|
||||
echo "Deleting existing release: {$tag} (id: {$existingId})\n";
|
||||
|
||||
// Delete release
|
||||
$this->giteaApi("{$apiBase}/releases/{$existingId}", $token, 'DELETE');
|
||||
$this->gitApi("{$apiBase}/releases/{$existingId}", $token, 'DELETE');
|
||||
|
||||
// Delete tag
|
||||
$this->giteaApi("{$apiBase}/tags/{$tag}", $token, 'DELETE');
|
||||
$this->gitApi("{$apiBase}/tags/{$tag}", $token, 'DELETE');
|
||||
}
|
||||
|
||||
// ── Create new release ──────────────────────────────────────────────────────
|
||||
@@ -260,7 +260,7 @@ class ReleaseCreateCli extends CliFramework
|
||||
'prerelease' => $prerelease,
|
||||
]);
|
||||
|
||||
$newRelease = $this->giteaApi("{$apiBase}/releases", $token, 'POST', $payload !== false ? $payload : '{}');
|
||||
$newRelease = $this->gitApi("{$apiBase}/releases", $token, 'POST', $payload !== false ? $payload : '{}');
|
||||
if ($newRelease === null || empty($newRelease['id'])) {
|
||||
$this->log('ERROR', "Failed to create release at tag: {$tag}");
|
||||
return 1;
|
||||
@@ -274,7 +274,7 @@ class ReleaseCreateCli extends CliFramework
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function giteaApi(string $url, string $token, string $method = 'GET', ?string $body = null): ?array
|
||||
private function gitApi(string $url, string $token, string $method = 'GET', ?string $body = null): ?array
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
if ($ch === false) {
|
||||
|
||||
+16
-16
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/release_manage.php
|
||||
* BRIEF: Create/update Gitea releases, upload assets, update release body
|
||||
* BRIEF: Create/update Git releases, upload assets, update release body
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
@@ -23,7 +23,7 @@ class ReleaseManageCli extends CliFramework
|
||||
{
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setDescription('Create/update Gitea releases, upload assets, update release body');
|
||||
$this->setDescription('Create/update Git releases, upload assets, update release body');
|
||||
$this->addArgument('--action', 'create | upload | update-body | delete', null);
|
||||
$this->addArgument('--tag', 'Release tag name', null);
|
||||
$this->addArgument('--name', 'Release name/title', null);
|
||||
@@ -31,8 +31,8 @@ class ReleaseManageCli extends CliFramework
|
||||
$this->addArgument('--body-file', 'Read body from file', null);
|
||||
$this->addArgument('--target', 'Target branch/commitish', 'main');
|
||||
$this->addArgument('--files', 'Comma-separated file paths to upload', null);
|
||||
$this->addArgument('--token', 'Gitea API token', null);
|
||||
$this->addArgument('--api-base', 'Gitea API base URL', null);
|
||||
$this->addArgument('--token', 'Git API token', null);
|
||||
$this->addArgument('--api-base', 'Git API base URL', null);
|
||||
}
|
||||
|
||||
protected function run(): int
|
||||
@@ -48,7 +48,7 @@ class ReleaseManageCli extends CliFramework
|
||||
$apiBase = $this->getArgument('--api-base');
|
||||
$files = $filesArg !== null ? array_filter(explode(',', $filesArg)) : [];
|
||||
if ($token === null) {
|
||||
$token = getenv('MOKOGITEA_TOKEN') ?: getenv('GITEA_TOKEN') ?: null;
|
||||
$token = getenv('MOKOGIT_TOKEN') ?: getenv('GIT_TOKEN') ?: null;
|
||||
}
|
||||
if ($bodyFile !== null && file_exists($bodyFile)) {
|
||||
$body = file_get_contents($bodyFile);
|
||||
@@ -62,12 +62,12 @@ class ReleaseManageCli extends CliFramework
|
||||
$existing = $this->getReleaseByTag($apiBase, $tag, $token);
|
||||
if ($existing !== null) {
|
||||
$existingId = $existing['id'];
|
||||
$this->releaseGiteaApi("{$apiBase}/releases/{$existingId}", 'DELETE', $token);
|
||||
$this->releaseGiteaApi("{$apiBase}/tags/{$tag}", 'DELETE', $token);
|
||||
$this->releaseGitApi("{$apiBase}/releases/{$existingId}", 'DELETE', $token);
|
||||
$this->releaseGitApi("{$apiBase}/tags/{$tag}", 'DELETE', $token);
|
||||
echo "Deleted previous release: {$tag} (id: {$existingId})\n";
|
||||
}
|
||||
$payload = json_encode(['tag_name' => $tag, 'name' => $name ?? $tag, 'body' => $body ?? '', 'target_commitish' => $target]);
|
||||
$result = $this->releaseGiteaApi("{$apiBase}/releases", 'POST', $token, $payload);
|
||||
$result = $this->releaseGitApi("{$apiBase}/releases", 'POST', $token, $payload);
|
||||
if ($result['code'] >= 200 && $result['code'] < 300) {
|
||||
$releaseId = $result['data']['id'] ?? 'unknown';
|
||||
echo "Release created: {$name} (tag: {$tag}, id: {$releaseId})\n";
|
||||
@@ -87,7 +87,7 @@ class ReleaseManageCli extends CliFramework
|
||||
return 1;
|
||||
}
|
||||
$releaseId = $release['id'];
|
||||
$assetsResult = $this->releaseGiteaApi("{$apiBase}/releases/{$releaseId}/assets", 'GET', $token);
|
||||
$assetsResult = $this->releaseGitApi("{$apiBase}/releases/{$releaseId}/assets", 'GET', $token);
|
||||
$existingAssets = $assetsResult['data'] ?? [];
|
||||
foreach ($files as $filePath) {
|
||||
$filePath = trim($filePath);
|
||||
@@ -98,13 +98,13 @@ class ReleaseManageCli extends CliFramework
|
||||
$fileName = basename($filePath);
|
||||
foreach ($existingAssets as $asset) {
|
||||
if (($asset['name'] ?? '') === $fileName) {
|
||||
$this->releaseGiteaApi("{$apiBase}/releases/{$releaseId}/assets/{$asset['id']}", 'DELETE', $token);
|
||||
$this->releaseGitApi("{$apiBase}/releases/{$releaseId}/assets/{$asset['id']}", 'DELETE', $token);
|
||||
echo "Deleted existing asset: {$fileName}\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
$uploadUrl = "{$apiBase}/releases/{$releaseId}/assets?name=" . urlencode($fileName);
|
||||
$result = $this->releaseGiteaApi($uploadUrl, 'POST', $token, null, $filePath);
|
||||
$result = $this->releaseGitApi($uploadUrl, 'POST', $token, null, $filePath);
|
||||
if ($result['code'] >= 200 && $result['code'] < 300) {
|
||||
echo "Uploaded: {$fileName}\n";
|
||||
} else {
|
||||
@@ -119,7 +119,7 @@ class ReleaseManageCli extends CliFramework
|
||||
return 1;
|
||||
}
|
||||
$payload = json_encode(['body' => $body ?? '']);
|
||||
$result = $this->releaseGiteaApi("{$apiBase}/releases/{$release['id']}", 'PATCH', $token, $payload);
|
||||
$result = $this->releaseGitApi("{$apiBase}/releases/{$release['id']}", 'PATCH', $token, $payload);
|
||||
if ($result['code'] >= 200 && $result['code'] < 300) {
|
||||
echo "Release body updated for tag: {$tag}\n";
|
||||
} else {
|
||||
@@ -130,8 +130,8 @@ class ReleaseManageCli extends CliFramework
|
||||
case 'delete':
|
||||
$existing = $this->getReleaseByTag($apiBase, $tag, $token);
|
||||
if ($existing !== null) {
|
||||
$this->releaseGiteaApi("{$apiBase}/releases/{$existing['id']}", 'DELETE', $token);
|
||||
$this->releaseGiteaApi("{$apiBase}/tags/{$tag}", 'DELETE', $token);
|
||||
$this->releaseGitApi("{$apiBase}/releases/{$existing['id']}", 'DELETE', $token);
|
||||
$this->releaseGitApi("{$apiBase}/tags/{$tag}", 'DELETE', $token);
|
||||
echo "Deleted: {$tag} (id: {$existing['id']})\n";
|
||||
} else {
|
||||
echo "No release found for tag: {$tag}\n";
|
||||
@@ -144,7 +144,7 @@ class ReleaseManageCli extends CliFramework
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function releaseGiteaApi(string $url, string $method, string $token, ?string $jsonBody = null, ?string $filePath = null): array
|
||||
private function releaseGitApi(string $url, string $method, string $token, ?string $jsonBody = null, ?string $filePath = null): array
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
$headers = ["Authorization: token {$token}"];
|
||||
@@ -166,7 +166,7 @@ class ReleaseManageCli extends CliFramework
|
||||
|
||||
private function getReleaseByTag(string $apiBase, string $tag, string $token): ?array
|
||||
{
|
||||
$result = $this->releaseGiteaApi("{$apiBase}/releases/tags/{$tag}", 'GET', $token);
|
||||
$result = $this->releaseGitApi("{$apiBase}/releases/tags/{$tag}", 'GET', $token);
|
||||
return ($result['code'] === 200 && isset($result['data']['id'])) ? $result['data'] : null;
|
||||
}
|
||||
}
|
||||
|
||||
+19
-19
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/release_mirror.php
|
||||
* BRIEF: Mirror a Gitea release (with assets) to a GitHub repository
|
||||
* BRIEF: Mirror a Git release (with assets) to a GitHub repository
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
@@ -23,11 +23,11 @@ class ReleaseMirrorCli extends CliFramework
|
||||
{
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setDescription('Mirror a Gitea release (with assets) to a GitHub repository');
|
||||
$this->setDescription('Mirror a Git release (with assets) to a GitHub repository');
|
||||
$this->addArgument('--version', 'Version string (required)', '');
|
||||
$this->addArgument('--tag', 'Release tag name (required)', '');
|
||||
$this->addArgument('--token', 'Gitea API token', '');
|
||||
$this->addArgument('--api-base', 'Gitea API base URL for the repo (required)', '');
|
||||
$this->addArgument('--token', 'Git API token', '');
|
||||
$this->addArgument('--api-base', 'Git API base URL for the repo (required)', '');
|
||||
$this->addArgument('--gh-token', 'GitHub personal access token', '');
|
||||
$this->addArgument('--gh-repo', 'GitHub org/repo (required)', '');
|
||||
$this->addArgument('--branch', 'Target branch (default: main)', 'main');
|
||||
@@ -44,30 +44,30 @@ class ReleaseMirrorCli extends CliFramework
|
||||
$branch = $this->getArgument('--branch');
|
||||
|
||||
// Allow tokens from environment
|
||||
$token = $token ?: (getenv('MOKOGITEA_TOKEN') ?: (getenv('GITEA_TOKEN') ?: ''));
|
||||
$token = $token ?: (getenv('MOKOGIT_TOKEN') ?: (getenv('GIT_TOKEN') ?: ''));
|
||||
$ghToken = $ghToken ?: (getenv('GH_MIRROR_TOKEN') ?: '');
|
||||
|
||||
if ($version === '' || $tag === '' || $token === '' || $apiBase === '' || $ghToken === '' || $ghRepo === '') {
|
||||
$this->log('ERROR', "Usage: release_mirror.php --version VER --tag TAG --token TOKEN " .
|
||||
"--api-base URL --gh-token GH_MIRROR_TOKEN --gh-repo org/repo [--branch main]");
|
||||
$this->log('ERROR', " --token: Gitea token (or MOKOGITEA_TOKEN / GITEA_TOKEN env)");
|
||||
$this->log('ERROR', " --token: Git token (or MOKOGIT_TOKEN / GIT_TOKEN env)");
|
||||
$this->log('ERROR', " --gh-token: GitHub token (or GH_MIRROR_TOKEN env)");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ── Step 1: Get Gitea release by tag ─────────────────────────────────────────
|
||||
// ── Step 1: Get Git release by tag ─────────────────────────────────────────
|
||||
|
||||
echo "Fetching Gitea release: {$tag}\n";
|
||||
$giteaRelease = $this->giteaApi("{$apiBase}/releases/tags/{$tag}", $token);
|
||||
if (!$giteaRelease || empty($giteaRelease['id'])) {
|
||||
$this->log('ERROR', "No Gitea release found with tag: {$tag}");
|
||||
echo "Fetching Git release: {$tag}\n";
|
||||
$gitRelease = $this->gitApi("{$apiBase}/releases/tags/{$tag}", $token);
|
||||
if (!$gitRelease || empty($gitRelease['id'])) {
|
||||
$this->log('ERROR', "No Git release found with tag: {$tag}");
|
||||
return 1;
|
||||
}
|
||||
|
||||
$giteaId = $giteaRelease['id'];
|
||||
$releaseName = $giteaRelease['name'] ?? "{$version}";
|
||||
$releaseBody = $giteaRelease['body'] ?? '';
|
||||
$assets = $giteaRelease['assets'] ?? [];
|
||||
$gitId = $gitRelease['id'];
|
||||
$releaseName = $gitRelease['name'] ?? "{$version}";
|
||||
$releaseBody = $gitRelease['body'] ?? '';
|
||||
$assets = $gitRelease['assets'] ?? [];
|
||||
|
||||
echo " Name: {$releaseName}\n";
|
||||
echo " Assets: " . count($assets) . " file(s)\n";
|
||||
@@ -109,7 +109,7 @@ class ReleaseMirrorCli extends CliFramework
|
||||
echo " Created GitHub release (id: {$ghReleaseId})\n";
|
||||
}
|
||||
|
||||
// ── Step 3: Download assets from Gitea ───────────────────────────────────────
|
||||
// ── Step 3: Download assets from Git ───────────────────────────────────────
|
||||
|
||||
$tmpDir = sys_get_temp_dir() . '/moko-mirror-' . getmypid();
|
||||
@mkdir($tmpDir, 0755, true);
|
||||
@@ -126,7 +126,7 @@ class ReleaseMirrorCli extends CliFramework
|
||||
$localPath = "{$tmpDir}/{$name}";
|
||||
echo " Downloading: {$name}\n";
|
||||
|
||||
if (!$this->giteaDownload($downloadUrl, $token, $localPath)) {
|
||||
if (!$this->gitDownload($downloadUrl, $token, $localPath)) {
|
||||
$this->log('ERROR', " Failed to download: {$name}");
|
||||
continue;
|
||||
}
|
||||
@@ -151,7 +151,7 @@ class ReleaseMirrorCli extends CliFramework
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function giteaApi(string $url, string $token, string $method = 'GET', ?string $body = null): ?array
|
||||
private function gitApi(string $url, string $token, string $method = 'GET', ?string $body = null): ?array
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
curl_setopt_array($ch, [
|
||||
@@ -176,7 +176,7 @@ class ReleaseMirrorCli extends CliFramework
|
||||
return json_decode($response, true) ?: null;
|
||||
}
|
||||
|
||||
private function giteaDownload(string $url, string $token, string $dest): bool
|
||||
private function gitDownload(string $url, string $token, string $dest): bool
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
$fp = fopen($dest, 'wb');
|
||||
|
||||
+15
-15
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/release_package.php
|
||||
* BRIEF: Build packages (ZIP + tar.gz) with SHA-256 and upload to Gitea release
|
||||
* BRIEF: Build packages (ZIP + tar.gz) with SHA-256 and upload to Git release
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
@@ -35,12 +35,12 @@ class ReleasePackageCli extends CliFramework
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setDescription('Build packages (ZIP + tar.gz) with SHA-256 and upload to Gitea release');
|
||||
$this->setDescription('Build packages (ZIP + tar.gz) with SHA-256 and upload to Git release');
|
||||
$this->addArgument('--path', 'Repository root path', '.');
|
||||
$this->addArgument('--version', 'Release version', '');
|
||||
$this->addArgument('--tag', 'Release tag name', '');
|
||||
$this->addArgument('--token', 'Gitea API token', '');
|
||||
$this->addArgument('--api-base', 'Gitea API base URL', '');
|
||||
$this->addArgument('--token', 'Git API token', '');
|
||||
$this->addArgument('--api-base', 'Git API base URL', '');
|
||||
$this->addArgument('--repo', 'Repo name for element detection fallback', '');
|
||||
$this->addArgument('--output', 'Output directory for built packages', '');
|
||||
}
|
||||
@@ -61,23 +61,23 @@ class ReleasePackageCli extends CliFramework
|
||||
|
||||
// Allow token from environment
|
||||
if ($token === '' || $token === null) {
|
||||
$token = getenv('MOKOGITEA_TOKEN') ?: (getenv('GITEA_TOKEN') ?: '');
|
||||
$token = getenv('MOKOGIT_TOKEN') ?: (getenv('GIT_TOKEN') ?: '');
|
||||
}
|
||||
|
||||
if ($version === '' || $tag === '' || $token === '' || $apiBase === '') {
|
||||
$this->log('ERROR', "Usage: release_package.php --path . --version VER --tag TAG --token TOKEN --api-base URL");
|
||||
$this->log('ERROR', " --repo REPO Repo name for element detection fallback");
|
||||
$this->log('ERROR', " --output DIR Output directory for built packages (default: sys_get_temp_dir())");
|
||||
$this->log('ERROR', " Token can also be set via MOKOGITEA_TOKEN or GITEA_TOKEN env var");
|
||||
$this->log('ERROR', " Token can also be set via MOKOGIT_TOKEN or GIT_TOKEN env var");
|
||||
return 1;
|
||||
}
|
||||
|
||||
$root = realpath($path) ?: $path;
|
||||
|
||||
// ── Read platform from .mokogitea/manifest.xml ───────────────────────
|
||||
// ── Read platform from .mokogit/manifest.xml ───────────────────────
|
||||
$detectedPlatform = 'generic';
|
||||
$detectedEntryPoint = '';
|
||||
$mokoManifest = "{$root}/.mokogitea/manifest.xml";
|
||||
$mokoManifest = "{$root}/.mokogit/manifest.xml";
|
||||
if (file_exists($mokoManifest)) {
|
||||
$mokoXml = @simplexml_load_file($mokoManifest);
|
||||
if ($mokoXml !== false) {
|
||||
@@ -458,7 +458,7 @@ class ReleasePackageCli extends CliFramework
|
||||
}
|
||||
|
||||
// ── Get release ID from tag ──────────────────────────────────────────
|
||||
$result = $this->giteaApiRequest("{$apiBase}/releases/tags/{$tag}", $token);
|
||||
$result = $this->gitApiRequest("{$apiBase}/releases/tags/{$tag}", $token);
|
||||
if ($result['data'] === null || !isset($result['data']['id'])) {
|
||||
$this->log('ERROR', "No release found for tag: {$tag} (HTTP {$result['code']})");
|
||||
return 1;
|
||||
@@ -468,7 +468,7 @@ class ReleasePackageCli extends CliFramework
|
||||
echo "Release ID: {$releaseId} (tag: {$tag})\n";
|
||||
|
||||
// ── Delete existing assets with same names ───────────────────────────
|
||||
$assetsResult = $this->giteaApiRequest("{$apiBase}/releases/{$releaseId}/assets", $token);
|
||||
$assetsResult = $this->gitApiRequest("{$apiBase}/releases/{$releaseId}/assets", $token);
|
||||
$existingAssets = $assetsResult['data'] ?? [];
|
||||
|
||||
$uploadNames = [
|
||||
@@ -485,7 +485,7 @@ class ReleasePackageCli extends CliFramework
|
||||
$assetName = $asset['name'] ?? '';
|
||||
$assetId = $asset['id'] ?? 0;
|
||||
if (in_array($assetName, $uploadNames, true) && $assetId > 0) {
|
||||
$this->giteaApiRequest("{$apiBase}/releases/{$releaseId}/assets/{$assetId}", $token, 'DELETE');
|
||||
$this->gitApiRequest("{$apiBase}/releases/{$releaseId}/assets/{$assetId}", $token, 'DELETE');
|
||||
echo "Deleted existing asset: {$assetName}\n";
|
||||
}
|
||||
}
|
||||
@@ -506,7 +506,7 @@ class ReleasePackageCli extends CliFramework
|
||||
}
|
||||
|
||||
$uploadUrl = "{$apiBase}/releases/{$releaseId}/assets?name=" . urlencode($name);
|
||||
$httpCode = $this->giteaUploadAsset($uploadUrl, $token, $localPath);
|
||||
$httpCode = $this->gitUploadAsset($uploadUrl, $token, $localPath);
|
||||
$status = ($httpCode >= 200 && $httpCode < 300) ? 'OK' : "FAILED ({$httpCode})";
|
||||
echo "Upload: {$name} — {$status}\n";
|
||||
|
||||
@@ -527,11 +527,11 @@ class ReleasePackageCli extends CliFramework
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a Gitea API request.
|
||||
* Perform a Git API request.
|
||||
*
|
||||
* @return array{data: array<string, mixed>|null, code: int}
|
||||
*/
|
||||
private function giteaApiRequest(string $url, string $token, string $method = 'GET', ?string $body = null): array
|
||||
private function gitApiRequest(string $url, string $token, string $method = 'GET', ?string $body = null): array
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
if ($ch === false) {
|
||||
@@ -564,7 +564,7 @@ class ReleasePackageCli extends CliFramework
|
||||
/**
|
||||
* Upload a file as a release asset.
|
||||
*/
|
||||
private function giteaUploadAsset(string $url, string $token, string $filePath): int
|
||||
private function gitUploadAsset(string $url, string $token, string $filePath): int
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
if ($ch === false) {
|
||||
|
||||
+17
-17
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/release_promote.php
|
||||
* BRIEF: Promote a Gitea release from one channel to another (rename release, tag, assets)
|
||||
* BRIEF: Promote a Git release from one channel to another (rename release, tag, assets)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
@@ -23,11 +23,11 @@ class ReleasePromoteCli extends CliFramework
|
||||
{
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setDescription('Promote a Gitea release from one channel to another');
|
||||
$this->setDescription('Promote a Git release from one channel to another');
|
||||
$this->addArgument('--from', 'Source channel (or "auto")', '');
|
||||
$this->addArgument('--to', 'Target channel (required)', '');
|
||||
$this->addArgument('--token', 'Gitea API token', '');
|
||||
$this->addArgument('--api-base', 'Gitea API base URL for the repo', '');
|
||||
$this->addArgument('--token', 'Git API token', '');
|
||||
$this->addArgument('--api-base', 'Git API base URL for the repo', '');
|
||||
$this->addArgument('--path', 'Repository root for type prefix detection', '.');
|
||||
$this->addArgument('--branch', 'Target branch', 'main');
|
||||
}
|
||||
@@ -41,7 +41,7 @@ class ReleasePromoteCli extends CliFramework
|
||||
$path = $this->getArgument('--path');
|
||||
$branch = $this->getArgument('--branch');
|
||||
|
||||
$token = $token ?: (getenv('MOKOGITEA_TOKEN') ?: (getenv('GITEA_TOKEN') ?: null));
|
||||
$token = $token ?: (getenv('MOKOGIT_TOKEN') ?: (getenv('GIT_TOKEN') ?: null));
|
||||
|
||||
if ($to === null || $token === null || $apiBase === null) {
|
||||
$this->log('ERROR', "Usage: release_promote.php --from <channel|auto> --to <channel> --token TOKEN --api-base URL [--path .]");
|
||||
@@ -64,7 +64,7 @@ class ReleasePromoteCli extends CliFramework
|
||||
// ── Resolve --from auto ──────────────────────────────────────────────────────
|
||||
if ($from === 'auto') {
|
||||
foreach ($channelOrder as $candidate) {
|
||||
$data = $this->giteaApi("{$apiBase}/releases/tags/{$candidate}", $token);
|
||||
$data = $this->gitApi("{$apiBase}/releases/tags/{$candidate}", $token);
|
||||
if ($data && !empty($data['id'])) {
|
||||
$from = $candidate;
|
||||
echo "Auto-detected source channel: {$from}\n";
|
||||
@@ -78,7 +78,7 @@ class ReleasePromoteCli extends CliFramework
|
||||
}
|
||||
|
||||
// ── Find source release ──────────────────────────────────────────────────────
|
||||
$sourceRelease = $this->giteaApi("{$apiBase}/releases/tags/{$from}", $token);
|
||||
$sourceRelease = $this->gitApi("{$apiBase}/releases/tags/{$from}", $token);
|
||||
if (!$sourceRelease || empty($sourceRelease['id'])) {
|
||||
$this->log('ERROR', "No release found with tag: {$from}");
|
||||
return 1;
|
||||
@@ -90,7 +90,7 @@ class ReleasePromoteCli extends CliFramework
|
||||
echo "Source: {$from} (id: {$sourceId}) — {$sourceName}\n";
|
||||
|
||||
// ── Get source assets ────────────────────────────────────────────────────────
|
||||
$assets = $this->giteaApi("{$apiBase}/releases/{$sourceId}/assets", $token) ?: [];
|
||||
$assets = $this->gitApi("{$apiBase}/releases/{$sourceId}/assets", $token) ?: [];
|
||||
echo "Assets: " . count($assets) . " file(s)\n";
|
||||
|
||||
// ── Download assets to temp ──────────────────────────────────────────────────
|
||||
@@ -101,7 +101,7 @@ class ReleasePromoteCli extends CliFramework
|
||||
$name = $asset['name'];
|
||||
$downloadUrl = $asset['browser_download_url'];
|
||||
echo " Downloading: {$name}\n";
|
||||
$this->giteaDownload($downloadUrl, $token, "{$tmpDir}/{$name}");
|
||||
$this->gitDownload($downloadUrl, $token, "{$tmpDir}/{$name}");
|
||||
}
|
||||
|
||||
// ── Detect type prefix for stable promotion ──────────────────────────────────
|
||||
@@ -188,15 +188,15 @@ class ReleasePromoteCli extends CliFramework
|
||||
}
|
||||
|
||||
// ── Delete source release + tag ──────────────────────────────────────────────
|
||||
$this->giteaApi("{$apiBase}/releases/{$sourceId}", $token, 'DELETE');
|
||||
$this->giteaApi("{$apiBase}/tags/{$from}", $token, 'DELETE');
|
||||
$this->gitApi("{$apiBase}/releases/{$sourceId}", $token, 'DELETE');
|
||||
$this->gitApi("{$apiBase}/tags/{$from}", $token, 'DELETE');
|
||||
echo "Deleted source: {$from} release + tag\n";
|
||||
|
||||
// ── Delete existing target release + tag (if any) ────────────────────────────
|
||||
$existingTarget = $this->giteaApi("{$apiBase}/releases/tags/{$to}", $token);
|
||||
$existingTarget = $this->gitApi("{$apiBase}/releases/tags/{$to}", $token);
|
||||
if ($existingTarget && !empty($existingTarget['id'])) {
|
||||
$this->giteaApi("{$apiBase}/releases/{$existingTarget['id']}", $token, 'DELETE');
|
||||
$this->giteaApi("{$apiBase}/tags/{$to}", $token, 'DELETE');
|
||||
$this->gitApi("{$apiBase}/releases/{$existingTarget['id']}", $token, 'DELETE');
|
||||
$this->gitApi("{$apiBase}/tags/{$to}", $token, 'DELETE');
|
||||
echo "Deleted existing target: {$to} release + tag\n";
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ class ReleasePromoteCli extends CliFramework
|
||||
'prerelease' => $isPrerelease,
|
||||
]);
|
||||
|
||||
$newRelease = $this->giteaApi("{$apiBase}/releases", $token, 'POST', $payload);
|
||||
$newRelease = $this->gitApi("{$apiBase}/releases", $token, 'POST', $payload);
|
||||
if (!$newRelease || empty($newRelease['id'])) {
|
||||
$this->log('ERROR', "Failed to create {$to} release");
|
||||
return 1;
|
||||
@@ -263,7 +263,7 @@ class ReleasePromoteCli extends CliFramework
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function giteaApi(string $url, string $token, string $method = 'GET', ?string $body = null): ?array
|
||||
private function gitApi(string $url, string $token, string $method = 'GET', ?string $body = null): ?array
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
curl_setopt_array($ch, [
|
||||
@@ -288,7 +288,7 @@ class ReleasePromoteCli extends CliFramework
|
||||
return json_decode($response, true) ?: null;
|
||||
}
|
||||
|
||||
private function giteaDownload(string $url, string $token, string $dest): bool
|
||||
private function gitDownload(string $url, string $token, string $dest): bool
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
$fp = fopen($dest, 'wb');
|
||||
|
||||
+16
-16
@@ -27,10 +27,10 @@ class ReleasePublishCli extends CliFramework
|
||||
$this->setDescription('Publish a release and update stability streams');
|
||||
$this->addArgument('--path', 'Repository root (default: .)', '.');
|
||||
$this->addArgument('--stability', 'Target stability: dev|alpha|beta|rc|stable (required)', '');
|
||||
$this->addArgument('--token', 'Gitea API token (required)', '');
|
||||
$this->addArgument('--token', 'Git API token (required)', '');
|
||||
$this->addArgument('--bump', 'Version bump type: patch|minor|none (default: none)', 'none');
|
||||
$this->addArgument('--branch', 'Current branch (default: auto-detect)', '');
|
||||
$this->addArgument('--gitea-url', 'Gitea URL', '');
|
||||
$this->addArgument('--git-url', 'Git URL', '');
|
||||
$this->addArgument('--org', 'Organization', '');
|
||||
$this->addArgument('--repo', 'Repository name', '');
|
||||
$this->addArgument('--repo-url', 'Repository URL for git auth', '');
|
||||
@@ -44,9 +44,9 @@ class ReleasePublishCli extends CliFramework
|
||||
$token = $this->getArgument('--token');
|
||||
$bumpType = $this->getArgument('--bump');
|
||||
$branch = $this->getArgument('--branch');
|
||||
$giteaUrl = $this->getArgument('--gitea-url') ?: (getenv('GITEA_URL') ?: 'https://git.mokoconsulting.tech');
|
||||
$org = $this->getArgument('--org') ?: (getenv('GITEA_ORG') ?: '');
|
||||
$repo = $this->getArgument('--repo') ?: (getenv('GITEA_REPO') ?: '');
|
||||
$gitUrl = $this->getArgument('--git-url') ?: (getenv('GIT_URL') ?: 'https://git.mokoconsulting.tech');
|
||||
$org = $this->getArgument('--org') ?: (getenv('GIT_ORG') ?: '');
|
||||
$repo = $this->getArgument('--repo') ?: (getenv('GIT_REPO') ?: '');
|
||||
$repoUrl = $this->getArgument('--repo-url');
|
||||
$skipUpdateStream = $this->getArgument('--skip-update-stream');
|
||||
|
||||
@@ -57,7 +57,7 @@ class ReleasePublishCli extends CliFramework
|
||||
|
||||
$cli = __DIR__;
|
||||
$php = '"' . PHP_BINARY . '"';
|
||||
$giteaUrl = rtrim($giteaUrl, '/');
|
||||
$gitUrl = rtrim($gitUrl, '/');
|
||||
|
||||
// Resolve path early for shell commands (Windows needs native paths)
|
||||
$resolvedPath = realpath($path) ?: $path;
|
||||
@@ -81,7 +81,7 @@ class ReleasePublishCli extends CliFramework
|
||||
|
||||
// Auto-construct repo URL for git auth if not provided
|
||||
if (empty($repoUrl) && !empty($token) && !empty($org) && !empty($repo)) {
|
||||
$host = preg_replace('#^https?://#', '', $giteaUrl);
|
||||
$host = preg_replace('#^https?://#', '', $gitUrl);
|
||||
$repoUrl = "https://x-access-token:{$token}@{$host}/{$org}/{$repo}.git";
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ class ReleasePublishCli extends CliFramework
|
||||
));
|
||||
}
|
||||
|
||||
$apiBase = "{$giteaUrl}/api/v1/repos/{$org}/{$repo}";
|
||||
$apiBase = "{$gitUrl}/api/v1/repos/{$org}/{$repo}";
|
||||
|
||||
// Stability ordering and suffix mapping
|
||||
$allStabilities = ['dev', 'alpha', 'beta', 'rc', 'stable'];
|
||||
@@ -189,11 +189,11 @@ class ReleasePublishCli extends CliFramework
|
||||
$cdR = $cdPfx . escapeshellarg($root);
|
||||
@shell_exec(
|
||||
$cdR . " && git config --local user.email"
|
||||
. " \"gitea-actions[bot]@mokoconsulting.tech\""
|
||||
. " \"git-actions[bot]@mokoconsulting.tech\""
|
||||
);
|
||||
@shell_exec(
|
||||
$cdR . " && git config --local user.name"
|
||||
. " \"gitea-actions[bot]\""
|
||||
. " \"git-actions[bot]\""
|
||||
);
|
||||
if (!empty($repoUrl)) {
|
||||
@shell_exec(
|
||||
@@ -239,8 +239,8 @@ class ReleasePublishCli extends CliFramework
|
||||
@shell_exec(
|
||||
$cdR . " && git commit -m "
|
||||
. escapeshellarg($commitMsg)
|
||||
. " --author=\"gitea-actions[bot]"
|
||||
. " <gitea-actions[bot]@mokoconsulting.tech>\""
|
||||
. " --author=\"git-actions[bot]"
|
||||
. " <git-actions[bot]@mokoconsulting.tech>\""
|
||||
);
|
||||
$pushResult = @shell_exec(
|
||||
$cdR . " && git push origin "
|
||||
@@ -314,7 +314,7 @@ class ReleasePublishCli extends CliFramework
|
||||
passthru("{$php} {$cli}/updates_xml_build.php --path " . escapeshellarg($path)
|
||||
. " --version " . escapeshellarg($streamVersion)
|
||||
. " --stability " . escapeshellarg($stream)
|
||||
. " --gitea-url " . escapeshellarg($giteaUrl)
|
||||
. " --git-url " . escapeshellarg($gitUrl)
|
||||
. " --org " . escapeshellarg($org)
|
||||
. " --repo " . escapeshellarg($repo)
|
||||
. " {$shaFlag} 2>&1");
|
||||
@@ -339,8 +339,8 @@ class ReleasePublishCli extends CliFramework
|
||||
@shell_exec(
|
||||
$cdRt . " && git commit -m "
|
||||
. escapeshellarg($chMsg)
|
||||
. " --author=\"gitea-actions[bot]"
|
||||
. " <gitea-actions[bot]@mokoconsulting.tech>\""
|
||||
. " --author=\"git-actions[bot]"
|
||||
. " <git-actions[bot]@mokoconsulting.tech>\""
|
||||
);
|
||||
@shell_exec(
|
||||
$cdRt . " && git push origin "
|
||||
@@ -354,7 +354,7 @@ class ReleasePublishCli extends CliFramework
|
||||
. " --current " . escapeshellarg($branch) . " --all"
|
||||
. " --version " . escapeshellarg($releaseVersion)
|
||||
. " --token " . escapeshellarg($token)
|
||||
. " --gitea-url " . escapeshellarg($giteaUrl)
|
||||
. " --git-url " . escapeshellarg($gitUrl)
|
||||
. " --org " . escapeshellarg($org)
|
||||
. " --repo " . escapeshellarg($repo) . " 2>&1");
|
||||
} else {
|
||||
|
||||
@@ -49,7 +49,7 @@ class ReleaseValidateCli extends CliFramework
|
||||
}
|
||||
$root = realpath($path) ?: $path;
|
||||
if ($platform === null) {
|
||||
$manifestXml = "{$root}/.mokogitea/manifest.xml";
|
||||
$manifestXml = "{$root}/.mokogit/manifest.xml";
|
||||
if (file_exists($manifestXml)) {
|
||||
$mContent = file_get_contents($manifestXml);
|
||||
if (preg_match('/<platform>([^<]+)<\/platform>/', $mContent, $pm)) {
|
||||
|
||||
+5
-5
@@ -22,7 +22,7 @@ use MokoCli\{CliFramework, Config, PlatformAdapterFactory};
|
||||
* Interactive repo setup wizard.
|
||||
*
|
||||
* Walks through platform selection, generates config files, workflows,
|
||||
* and optionally creates the repo on Gitea via API.
|
||||
* and optionally creates the repo on Git via API.
|
||||
*
|
||||
* @see https://git.mokoconsulting.tech/MokoConsulting/mokocli/issues/145
|
||||
*/
|
||||
@@ -54,7 +54,7 @@ class RepoWizard extends CliFramework
|
||||
{
|
||||
$this->setDescription('Interactive configuration wizard for new repositories');
|
||||
$this->addArgument('--path', 'Directory to generate files in', '.');
|
||||
$this->addArgument('--create-remote', 'Create repo on Gitea via API', false);
|
||||
$this->addArgument('--create-remote', 'Create repo on Git via API', false);
|
||||
$this->addArgument('--non-interactive', 'Use defaults (no prompts)', false);
|
||||
}
|
||||
|
||||
@@ -155,8 +155,8 @@ class RepoWizard extends CliFramework
|
||||
break;
|
||||
}
|
||||
|
||||
// .mokogitea/workflows
|
||||
$generated[] = $this->writeFile($path, '.mokogitea/workflows/pr-check.yml',
|
||||
// .mokogit/workflows
|
||||
$generated[] = $this->writeFile($path, '.mokogit/workflows/pr-check.yml',
|
||||
"# PR check workflow — synced from mokocli templates\n# Run: moko sync to update\n");
|
||||
|
||||
// .gitignore
|
||||
@@ -205,7 +205,7 @@ class RepoWizard extends CliFramework
|
||||
$org = $this->answers['org'];
|
||||
|
||||
if ($this->dryRun) {
|
||||
$this->log('INFO', "[dry-run] Would create {$org}/{$this->answers['name']} on Gitea");
|
||||
$this->log('INFO', "[dry-run] Would create {$org}/{$this->answers['name']} on Git");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+14
-14
@@ -28,16 +28,16 @@ class ScaffoldClientCli extends CliFramework
|
||||
{
|
||||
$this->setDescription('Scaffold a new client-waas repo from Template-Client');
|
||||
$this->addArgument('--name', 'Client name', '');
|
||||
$this->addArgument('--org', 'Gitea organization', '');
|
||||
$this->addArgument('--gitea-url', 'Gitea URL', 'https://git.mokoconsulting.tech');
|
||||
$this->addArgument('--token', 'Gitea API token', '');
|
||||
$this->addArgument('--org', 'Git organization', '');
|
||||
$this->addArgument('--git-url', 'Git URL', 'https://git.mokoconsulting.tech');
|
||||
$this->addArgument('--token', 'Git API token', '');
|
||||
}
|
||||
|
||||
protected function run(): int
|
||||
{
|
||||
$name = $this->getArgument('--name');
|
||||
$org = $this->getArgument('--org');
|
||||
$giteaUrl = rtrim($this->getArgument('--gitea-url'), '/');
|
||||
$gitUrl = rtrim($this->getArgument('--git-url'), '/');
|
||||
$token = $this->getArgument('--token');
|
||||
if ($name === '' || $org === '' || $token === '') {
|
||||
$this->log('ERROR', '--name, --org, and --token are required.');
|
||||
@@ -45,11 +45,11 @@ class ScaffoldClientCli extends CliFramework
|
||||
}
|
||||
$repoName = 'client-waas-' . $name;
|
||||
$this->log('INFO', "Scaffolding client repo: {$org}/{$repoName}");
|
||||
$this->log('INFO', "Gitea URL: {$giteaUrl}");
|
||||
$this->log('INFO', "Git URL: {$gitUrl}");
|
||||
if ($this->dryRun) {
|
||||
$this->log('INFO', '[DRY RUN] Would create repo from template MokoConsulting/Template-Client');
|
||||
$this->log('INFO', "[DRY RUN] Repo: {$org}/{$repoName}");
|
||||
$this->printPostSetupInstructions($repoName, $giteaUrl, $org);
|
||||
$this->printPostSetupInstructions($repoName, $gitUrl, $org);
|
||||
return 0;
|
||||
}
|
||||
$this->log('INFO', 'Step 1: Creating repo from template...');
|
||||
@@ -65,7 +65,7 @@ class ScaffoldClientCli extends CliFramework
|
||||
$response = $this->apiRequest(
|
||||
'POST',
|
||||
"/api/v1/repos/MokoConsulting/Template-Client/generate",
|
||||
$giteaUrl,
|
||||
$gitUrl,
|
||||
$token,
|
||||
$createPayload
|
||||
);
|
||||
@@ -75,12 +75,12 @@ class ScaffoldClientCli extends CliFramework
|
||||
}
|
||||
$this->log('INFO', "Repo created: {$org}/{$repoName}");
|
||||
$this->log('INFO', 'Step 2: Updating repo description...');
|
||||
$this->apiRequest('PATCH', "/api/v1/repos/{$org}/{$repoName}", $giteaUrl, $token, json_encode(['description' => "{$name} WaaS site"]));
|
||||
$this->apiRequest('PATCH', "/api/v1/repos/{$org}/{$repoName}", $gitUrl, $token, json_encode(['description' => "{$name} WaaS site"]));
|
||||
$this->log('INFO', 'Step 3: Creating dev branch from main...');
|
||||
$response = $this->apiRequest(
|
||||
'POST',
|
||||
"/api/v1/repos/{$org}/{$repoName}/branches",
|
||||
$giteaUrl,
|
||||
$gitUrl,
|
||||
$token,
|
||||
json_encode([
|
||||
'new_branch_name' => 'dev',
|
||||
@@ -92,15 +92,15 @@ class ScaffoldClientCli extends CliFramework
|
||||
} else {
|
||||
$this->log('WARN', "Could not create dev branch (HTTP {$response['code']}).");
|
||||
}
|
||||
$this->printPostSetupInstructions($repoName, $giteaUrl, $org);
|
||||
$this->printPostSetupInstructions($repoName, $gitUrl, $org);
|
||||
$this->log('INFO', 'Scaffold complete.');
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function printPostSetupInstructions(string $repoName, string $giteaUrl, string $org): void
|
||||
private function printPostSetupInstructions(string $repoName, string $gitUrl, string $org): void
|
||||
{
|
||||
fwrite(STDERR, "\n=== POST-SETUP INSTRUCTIONS ===\n\n"
|
||||
. "Navigate to: {$giteaUrl}/{$org}/{$repoName}/settings\n\n"
|
||||
. "Navigate to: {$gitUrl}/{$org}/{$repoName}/settings\n\n"
|
||||
. "Set REPO VARIABLES:\n"
|
||||
. " DEV_SYNC_HOST, DEV_SYNC_PORT, DEV_SYNC_USER, DEV_SYNC_PATH\n"
|
||||
. " LIVE_SSH_HOST, LIVE_SSH_PORT, LIVE_SSH_USER, LIVE_SYNC_PATH\n\n"
|
||||
@@ -109,10 +109,10 @@ class ScaffoldClientCli extends CliFramework
|
||||
. "================================\n");
|
||||
}
|
||||
|
||||
private function apiRequest(string $method, string $endpoint, string $giteaUrl, string $token, ?string $body = null): array
|
||||
private function apiRequest(string $method, string $endpoint, string $gitUrl, string $token, ?string $body = null): array
|
||||
{
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $giteaUrl . $endpoint);
|
||||
curl_setopt($ch, CURLOPT_URL, $gitUrl . $endpoint);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json', 'Accept: application/json', "Authorization: token {$token}"]);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* BRIEF: Validate a client MokoOnyx theme package — required CSS variables
|
||||
* (derived dynamically from the MokoOnyx standard theme) are defined in
|
||||
* the client's light/dark custom CSS, required files exist, the manifest
|
||||
* is sane, and (optionally) the repo's Gitea metadata is set.
|
||||
* is sane, and (optionally) the repo's Git metadata is set.
|
||||
*
|
||||
* Standalone (no CliFramework dependency) so it runs even when the shared
|
||||
* framework autoloader is unavailable.
|
||||
@@ -166,7 +166,7 @@ if (is_file($manifest)) {
|
||||
if ($server === '') {
|
||||
$fail('<updateservers><server> is missing');
|
||||
} elseif (strpos($server, '/raw/branch/') !== false) {
|
||||
$fail('update server uses a legacy raw/branch URL; use the dynamic MokoGitea feed');
|
||||
$fail('update server uses a legacy raw/branch URL; use the dynamic MokoGit feed');
|
||||
} else {
|
||||
$ok("update server: $server");
|
||||
}
|
||||
@@ -224,12 +224,12 @@ if (is_file($manifest)) {
|
||||
}
|
||||
}
|
||||
|
||||
// 4) Repository metadata via Gitea API (optional) -------------------------
|
||||
// 4) Repository metadata via Git API (optional) -------------------------
|
||||
$apiBase = isset($opts['api-base']) && is_string($opts['api-base']) ? rtrim($opts['api-base'], '/') : '';
|
||||
$repoSlug = isset($opts['repo']) && is_string($opts['repo']) ? trim($opts['repo']) : '';
|
||||
$token = isset($opts['token']) && is_string($opts['token']) ? trim($opts['token']) : '';
|
||||
if ($apiBase !== '' && $repoSlug !== '' && $token !== '') {
|
||||
echo "\n=== Repository metadata (Gitea API) ===\n";
|
||||
echo "\n=== Repository metadata (Git API) ===\n";
|
||||
$url = "$apiBase/repos/$repoSlug";
|
||||
$ctx = stream_context_create(['http' => [
|
||||
'method' => 'GET',
|
||||
@@ -240,7 +240,7 @@ if ($apiBase !== '' && $repoSlug !== '' && $token !== '') {
|
||||
$resp = @file_get_contents($url, false, $ctx);
|
||||
$data = $resp !== false ? json_decode($resp, true) : null;
|
||||
if (!is_array($data) || !isset($data['name'])) {
|
||||
$fail("could not read repo metadata from Gitea API ($url)");
|
||||
$fail("could not read repo metadata from Git API ($url)");
|
||||
} else {
|
||||
trim((string) ($data['description'] ?? '')) !== '' ? $ok('description set')
|
||||
: $fail('repo description is empty');
|
||||
@@ -272,7 +272,7 @@ if ($apiBase !== '' && $repoSlug !== '' && $token !== '') {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo "\n=== Repository metadata (Gitea API) ===\n";
|
||||
echo "\n=== Repository metadata (Git API) ===\n";
|
||||
$note('API args not provided; skipping repo metadata check');
|
||||
}
|
||||
|
||||
|
||||
+10
-10
@@ -28,7 +28,7 @@ class UpdatesXmlBuildCli extends CliFramework
|
||||
$this->addArgument('--version', 'Version string (required)', '');
|
||||
$this->addArgument('--stability', 'One of: stable, rc, beta, alpha, development (default: stable)', 'stable');
|
||||
$this->addArgument('--sha', 'SHA-256 hash of the ZIP package', '');
|
||||
$this->addArgument('--gitea-url', 'Gitea instance URL', '');
|
||||
$this->addArgument('--git-url', 'Git instance URL', '');
|
||||
$this->addArgument('--org', 'Organization', '');
|
||||
$this->addArgument('--repo', 'Repository name', '');
|
||||
$this->addArgument('--output', 'Output file path (default: updates.xml in --path)', '');
|
||||
@@ -41,9 +41,9 @@ class UpdatesXmlBuildCli extends CliFramework
|
||||
$version = $this->getArgument('--version');
|
||||
$stability = $this->getArgument('--stability');
|
||||
$sha = $this->getArgument('--sha') ?: null;
|
||||
$giteaUrl = $this->getArgument('--gitea-url') ?: (getenv('GITEA_URL') ?: 'https://git.mokoconsulting.tech');
|
||||
$org = $this->getArgument('--org') ?: (getenv('GITEA_ORG') ?: '');
|
||||
$repo = $this->getArgument('--repo') ?: (getenv('GITEA_REPO') ?: '');
|
||||
$gitUrl = $this->getArgument('--git-url') ?: (getenv('GIT_URL') ?: 'https://git.mokoconsulting.tech');
|
||||
$org = $this->getArgument('--org') ?: (getenv('GIT_ORG') ?: '');
|
||||
$repo = $this->getArgument('--repo') ?: (getenv('GIT_REPO') ?: '');
|
||||
$outputFile = $this->getArgument('--output') ?: null;
|
||||
$githubOutput = $this->getArgument('--github-output');
|
||||
|
||||
@@ -57,12 +57,12 @@ class UpdatesXmlBuildCli extends CliFramework
|
||||
|
||||
$root = realpath($path) ?: $path;
|
||||
|
||||
// -- Read platform from .mokogitea/manifest.xml --------------------------------
|
||||
// -- Read platform from .mokogit/manifest.xml --------------------------------
|
||||
$detectedPlatform = 'joomla';
|
||||
$detectedName = $repo;
|
||||
$detectedPackageType = '';
|
||||
$detectedDisplayName = '';
|
||||
$mokoManifest = "{$root}/.mokogitea/manifest.xml";
|
||||
$mokoManifest = "{$root}/.mokogit/manifest.xml";
|
||||
if (file_exists($mokoManifest)) {
|
||||
$mokoXml = @simplexml_load_file($mokoManifest);
|
||||
if ($mokoXml !== false) {
|
||||
@@ -312,12 +312,12 @@ class UpdatesXmlBuildCli extends CliFramework
|
||||
|
||||
// -- Write ONLY the single channel being released --------------------------------
|
||||
$entries = [];
|
||||
$giteaTag = $releaseTagMap[$stability] ?? $stability;
|
||||
$gitTag = $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}";
|
||||
$channelDownloadUrl = "{$gitUrl}/{$org}/{$repo}/releases/download/{$gitTag}/{$typePrefix}{$extElement}-{$channelVersion}.zip";
|
||||
$channelInfoUrl = "{$gitUrl}/{$org}/{$repo}/releases/tag/{$gitTag}";
|
||||
$joomlaTag = $stabilityTagMap[$stability] ?? $stability;
|
||||
$changelogUrl = "{$giteaUrl}/{$org}/{$repo}/raw/branch/main/CHANGELOG.md";
|
||||
$changelogUrl = "{$gitUrl}/{$org}/{$repo}/raw/branch/main/CHANGELOG.md";
|
||||
|
||||
$entries[] = $this->buildEntry(
|
||||
$joomlaTag,
|
||||
|
||||
+16
-16
@@ -11,7 +11,7 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/updates_xml_sync.php
|
||||
* VERSION: 09.43.00
|
||||
* BRIEF: Sync updates.xml to target branches via Gitea API
|
||||
* BRIEF: Sync updates.xml to target branches via Git API
|
||||
* NOTE: Called by pre-release and auto-release workflows after updates.xml
|
||||
* is modified on the current branch. Pushes the file to other branches
|
||||
* without requiring a git checkout (avoids merge conflicts).
|
||||
@@ -27,14 +27,14 @@ class UpdatesXmlSyncCli extends CliFramework
|
||||
{
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setDescription('Sync updates.xml to target branches via Gitea API');
|
||||
$this->setDescription('Sync updates.xml to target branches via Git API');
|
||||
$this->addArgument('--path', 'Repository root containing updates.xml', '.');
|
||||
$this->addArgument('--branches', 'Comma-separated target branches to sync to', 'main,dev');
|
||||
$this->addArgument('--all', 'Auto-discover all branches via Gitea API', false);
|
||||
$this->addArgument('--all', 'Auto-discover all branches via Git API', false);
|
||||
$this->addArgument('--current', 'Current branch to skip (required)', '');
|
||||
$this->addArgument('--version', 'Version string for commit message', '');
|
||||
$this->addArgument('--token', 'Gitea API token', '');
|
||||
$this->addArgument('--gitea-url', 'Gitea instance URL', '');
|
||||
$this->addArgument('--token', 'Git API token', '');
|
||||
$this->addArgument('--git-url', 'Git instance URL', '');
|
||||
$this->addArgument('--org', 'Organization', '');
|
||||
$this->addArgument('--repo', 'Repository name', '');
|
||||
}
|
||||
@@ -47,22 +47,22 @@ class UpdatesXmlSyncCli extends CliFramework
|
||||
$current = $this->getArgument('--current');
|
||||
$version = $this->getArgument('--version');
|
||||
$token = $this->getArgument('--token');
|
||||
$giteaUrl = $this->getArgument('--gitea-url');
|
||||
$gitUrl = $this->getArgument('--git-url');
|
||||
$org = $this->getArgument('--org');
|
||||
$repo = $this->getArgument('--repo');
|
||||
|
||||
// Fall back to environment variables
|
||||
if ($token === '') {
|
||||
$token = getenv('MOKOGITEA_TOKEN') ?: '';
|
||||
$token = getenv('MOKOGIT_TOKEN') ?: '';
|
||||
}
|
||||
if ($giteaUrl === '') {
|
||||
$giteaUrl = getenv('GITEA_URL') ?: 'https://git.mokoconsulting.tech';
|
||||
if ($gitUrl === '') {
|
||||
$gitUrl = getenv('GIT_URL') ?: 'https://git.mokoconsulting.tech';
|
||||
}
|
||||
if ($org === '') {
|
||||
$org = getenv('GITEA_ORG') ?: '';
|
||||
$org = getenv('GIT_ORG') ?: '';
|
||||
}
|
||||
if ($repo === '') {
|
||||
$repo = getenv('GITEA_REPO') ?: '';
|
||||
$repo = getenv('GIT_REPO') ?: '';
|
||||
}
|
||||
|
||||
if ($current === '') {
|
||||
@@ -71,18 +71,18 @@ class UpdatesXmlSyncCli extends CliFramework
|
||||
}
|
||||
|
||||
if ($token === '') {
|
||||
$this->log('ERROR', '--token or MOKOGITEA_TOKEN env is required');
|
||||
$this->log('ERROR', '--token or MOKOGIT_TOKEN env is required');
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ($org === '' || $repo === '') {
|
||||
$this->log('ERROR', '--org and --repo (or GITEA_ORG/GITEA_REPO env) are required');
|
||||
$this->log('ERROR', '--org and --repo (or GIT_ORG/GIT_REPO env) are required');
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Auto-discover branches if --all flag is set
|
||||
if ($discoverAll) {
|
||||
$apiUrl = "{$giteaUrl}/api/v1/repos/{$org}/{$repo}/branches?limit=50";
|
||||
$apiUrl = "{$gitUrl}/api/v1/repos/{$org}/{$repo}/branches?limit=50";
|
||||
$ch = curl_init($apiUrl);
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
@@ -118,8 +118,8 @@ class UpdatesXmlSyncCli extends CliFramework
|
||||
|
||||
$content = file_get_contents($updatesFile);
|
||||
$encoded = base64_encode($content);
|
||||
$giteaUrl = rtrim($giteaUrl, '/');
|
||||
$apiBase = "{$giteaUrl}/api/v1/repos/{$org}/{$repo}";
|
||||
$gitUrl = rtrim($gitUrl, '/');
|
||||
$apiBase = "{$gitUrl}/api/v1/repos/{$org}/{$repo}";
|
||||
$vLabel = $version !== '' ? " {$version}" : '';
|
||||
|
||||
$targets = array_filter(
|
||||
|
||||
@@ -70,7 +70,7 @@ class VersionAutoBumpCli extends CliFramework
|
||||
|
||||
// Auto-detect watch path from manifest.xml if not provided
|
||||
if (empty($watchPath)) {
|
||||
$manifestFile = realpath($path) . '/.mokogitea/manifest.xml';
|
||||
$manifestFile = realpath($path) . '/.mokogit/manifest.xml';
|
||||
if (file_exists($manifestFile)) {
|
||||
$xml = @simplexml_load_file($manifestFile);
|
||||
if ($xml && isset($xml->build->{'entry-point'})) {
|
||||
@@ -176,11 +176,11 @@ class VersionAutoBumpCli extends CliFramework
|
||||
$cdRoot = $cd . escapeshellarg($root);
|
||||
@shell_exec(
|
||||
$cdRoot . " && git config --local user.email"
|
||||
. " \"gitea-actions[bot]@mokoconsulting.tech\""
|
||||
. " \"git-actions[bot]@mokoconsulting.tech\""
|
||||
);
|
||||
@shell_exec(
|
||||
$cdRoot . " && git config --local user.name"
|
||||
. " \"gitea-actions[bot]\""
|
||||
. " \"git-actions[bot]\""
|
||||
);
|
||||
|
||||
if (!empty($repoUrl)) {
|
||||
@@ -196,8 +196,8 @@ class VersionAutoBumpCli extends CliFramework
|
||||
: "chore(version): set {$stability} suffix {$displayVersion} [skip ci]";
|
||||
@shell_exec(
|
||||
$cdRoot . " && git commit -m " . escapeshellarg($commitMsg)
|
||||
. " --author=\"gitea-actions[bot]"
|
||||
. " <gitea-actions[bot]@mokoconsulting.tech>\""
|
||||
. " --author=\"git-actions[bot]"
|
||||
. " <git-actions[bot]@mokoconsulting.tech>\""
|
||||
);
|
||||
|
||||
$pushResult = @shell_exec(
|
||||
|
||||
@@ -44,7 +44,7 @@ class VersionBumpCli extends CliFramework
|
||||
$mokoVersion = null;
|
||||
$existingSuffix = '';
|
||||
$versionPrefix = '';
|
||||
$mokoManifest = "{$root}/.mokogitea/manifest.xml";
|
||||
$mokoManifest = "{$root}/.mokogit/manifest.xml";
|
||||
$mokoContent = '';
|
||||
if (file_exists($mokoManifest)) {
|
||||
$mokoContent = file_get_contents($mokoManifest);
|
||||
@@ -363,7 +363,7 @@ class VersionBumpCli extends CliFramework
|
||||
if (in_array($relPath, $updatedFiles ?? [], true)) {
|
||||
continue;
|
||||
}
|
||||
if (strpos($relPath, '.mokogitea/manifest.xml') !== false) {
|
||||
if (strpos($relPath, '.mokogit/manifest.xml') !== false) {
|
||||
continue;
|
||||
}
|
||||
$content = @file_get_contents($filePath);
|
||||
|
||||
+13
-13
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/version_bump_remote.php
|
||||
* BRIEF: Bump version in manifest XML and CHANGELOG.md on a remote branch via Gitea API
|
||||
* BRIEF: Bump version in manifest XML and CHANGELOG.md on a remote branch via Git API
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
@@ -23,15 +23,15 @@ class VersionBumpRemoteCli extends CliFramework
|
||||
{
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setDescription('Bump version in manifest XML and CHANGELOG.md on a remote branch via Gitea API');
|
||||
$this->setDescription('Bump version in manifest XML and CHANGELOG.md on a remote branch via Git API');
|
||||
$this->addArgument('--path', 'Repository root', '.');
|
||||
$this->addArgument('--branch', 'Target branch to bump (required)', null);
|
||||
$this->addArgument('--bump', 'Bump type: patch | minor | major', 'minor');
|
||||
$this->addArgument('--token', 'Gitea API token (or MOKOGITEA_TOKEN env var)', null);
|
||||
$this->addArgument('--api-base', 'Gitea API base URL for the repo', null);
|
||||
$this->addArgument('--token', 'Git API token (or MOKOGIT_TOKEN env var)', null);
|
||||
$this->addArgument('--api-base', 'Git API base URL for the repo', null);
|
||||
$this->addArgument('--no-changelog', 'Skip CHANGELOG.md bump', false);
|
||||
$this->addArgument('--repo', 'Repository path (owner/repo)', null);
|
||||
$this->addArgument('--gitea-url', 'Gitea instance URL', null);
|
||||
$this->addArgument('--git-url', 'Git instance URL', null);
|
||||
}
|
||||
|
||||
protected function run(): int
|
||||
@@ -43,15 +43,15 @@ class VersionBumpRemoteCli extends CliFramework
|
||||
$apiBase = $this->getArgument('--api-base');
|
||||
$noChangelog = (bool) $this->getArgument('--no-changelog');
|
||||
$repo = $this->getArgument('--repo');
|
||||
$giteaUrl = $this->getArgument('--gitea-url');
|
||||
$gitUrl = $this->getArgument('--git-url');
|
||||
if ($token === null) {
|
||||
$token = getenv('MOKOGITEA_TOKEN') ?: getenv('GITEA_TOKEN') ?: null;
|
||||
$token = getenv('MOKOGIT_TOKEN') ?: getenv('GIT_TOKEN') ?: null;
|
||||
}
|
||||
if ($giteaUrl === null) {
|
||||
$giteaUrl = getenv('GITEA_URL') ?: 'https://git.mokoconsulting.tech';
|
||||
if ($gitUrl === null) {
|
||||
$gitUrl = getenv('GIT_URL') ?: 'https://git.mokoconsulting.tech';
|
||||
}
|
||||
if ($apiBase === null && $repo !== null) {
|
||||
$apiBase = rtrim($giteaUrl, '/') . '/api/v1/repos/' . $repo;
|
||||
$apiBase = rtrim($gitUrl, '/') . '/api/v1/repos/' . $repo;
|
||||
}
|
||||
if ($branch === null || $token === null || $apiBase === null) {
|
||||
$this->log('ERROR', "Usage: version_bump_remote.php --branch BRANCH --token TOKEN --api-base URL [--bump minor|patch|major]");
|
||||
@@ -148,7 +148,7 @@ class VersionBumpRemoteCli extends CliFramework
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function giteaApi(string $method, string $url, string $token, ?string $body = null): ?array
|
||||
private function gitApi(string $method, string $url, string $token, ?string $body = null): ?array
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
curl_setopt_array($ch, [
|
||||
@@ -180,7 +180,7 @@ class VersionBumpRemoteCli extends CliFramework
|
||||
callable $transform,
|
||||
string $commitMessage
|
||||
): bool {
|
||||
$file = $this->giteaApi('GET', "{$apiBase}/contents/{$filePath}?ref={$branch}", $token);
|
||||
$file = $this->gitApi('GET', "{$apiBase}/contents/{$filePath}?ref={$branch}", $token);
|
||||
if ($file === null || !isset($file['sha']) || !isset($file['content'])) {
|
||||
return false;
|
||||
}
|
||||
@@ -191,7 +191,7 @@ class VersionBumpRemoteCli extends CliFramework
|
||||
return true;
|
||||
}
|
||||
$payload = json_encode(['content' => base64_encode($newContent), 'sha' => $file['sha'], 'message' => $commitMessage, 'branch' => $branch]);
|
||||
$result = $this->giteaApi('PUT', "{$apiBase}/contents/{$filePath}", $token, $payload);
|
||||
$result = $this->gitApi('PUT', "{$apiBase}/contents/{$filePath}", $token, $payload);
|
||||
if ($result === null) {
|
||||
$this->log('ERROR', "{$filePath}: failed to update");
|
||||
return false;
|
||||
|
||||
@@ -38,14 +38,14 @@ class VersionCheckCli extends CliFramework
|
||||
$root = realpath($path) ?: $path;
|
||||
$errors = 0;
|
||||
$versions = [];
|
||||
$mokoManifest = "{$root}/.mokogitea/manifest.xml";
|
||||
$mokoManifest = "{$root}/.mokogit/manifest.xml";
|
||||
if (file_exists($mokoManifest)) {
|
||||
$xml = @simplexml_load_file($mokoManifest);
|
||||
if ($xml !== false) {
|
||||
$v = (string)($xml->identity->version ?? '');
|
||||
$base = preg_replace('/(-(dev|alpha|beta|rc))+$/', '', $v);
|
||||
if (preg_match('/^\d{2}\.\d{2}\.\d{2}$/', $base)) {
|
||||
$versions['.mokogitea/manifest.xml'] = $base;
|
||||
$versions['.mokogit/manifest.xml'] = $base;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,7 +124,7 @@ class VersionCheckCli extends CliFramework
|
||||
file_put_contents($readme, $updated);
|
||||
} echo " Fixed: README.md -> {$highestVersion}\n";
|
||||
}
|
||||
if (isset($versions['.mokogitea/manifest.xml']) && $versions['.mokogitea/manifest.xml'] !== $highestVersion) {
|
||||
if (isset($versions['.mokogit/manifest.xml']) && $versions['.mokogit/manifest.xml'] !== $highestVersion) {
|
||||
$content = file_get_contents($mokoManifest);
|
||||
$vPat = '#<version>\d{2}\.\d{2}\.\d{2}'
|
||||
. '(?:(?:-(?:dev|alpha|beta|rc))+)?</version>#';
|
||||
@@ -137,7 +137,7 @@ class VersionCheckCli extends CliFramework
|
||||
if ($updated !== null) {
|
||||
$updated = preg_replace('#(\s*<version>[^<]*</version>)\s*<version>[^<]*</version>#', '$1', $updated);
|
||||
file_put_contents($mokoManifest, $updated);
|
||||
} echo " Fixed: .mokogitea/manifest.xml -> {$highestVersion}\n";
|
||||
} echo " Fixed: .mokogit/manifest.xml -> {$highestVersion}\n";
|
||||
}
|
||||
if (isset($versions['CHANGELOG.md']) && $versions['CHANGELOG.md'] !== $highestVersion) {
|
||||
$content = file_get_contents($changelog);
|
||||
@@ -179,7 +179,7 @@ class VersionCheckCli extends CliFramework
|
||||
} echo " Fixed: pyproject.toml -> {$highestVersion}\n";
|
||||
}
|
||||
foreach ($versions as $source => $ver) {
|
||||
if (in_array($source, ['README.md', 'CHANGELOG.md', '.mokogitea/manifest.xml', 'package.json', 'pyproject.toml'], true)) {
|
||||
if (in_array($source, ['README.md', 'CHANGELOG.md', '.mokogit/manifest.xml', 'package.json', 'pyproject.toml'], true)) {
|
||||
continue;
|
||||
} if ($ver === $highestVersion) {
|
||||
continue;
|
||||
|
||||
@@ -32,10 +32,10 @@ class VersionReadCli extends CliFramework
|
||||
$path = $this->getArgument('--path');
|
||||
$root = realpath($path) ?: $path;
|
||||
|
||||
// -- 1. Read from .mokogitea/manifest.xml (canonical source) --
|
||||
// -- 1. Read from .mokogit/manifest.xml (canonical source) --
|
||||
$mokoVersion = null;
|
||||
$versionPrefix = '';
|
||||
$mokoManifest = "{$root}/.mokogitea/manifest.xml";
|
||||
$mokoManifest = "{$root}/.mokogit/manifest.xml";
|
||||
if (file_exists($mokoManifest)) {
|
||||
$xml = @simplexml_load_file($mokoManifest);
|
||||
if ($xml !== false) {
|
||||
|
||||
+11
-11
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/version_reset_dev.php
|
||||
* BRIEF: Reset platform version to 'development' on a branch via Gitea API
|
||||
* BRIEF: Reset platform version to 'development' on a branch via Git API
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
@@ -23,9 +23,9 @@ class VersionResetDevCli extends CliFramework
|
||||
{
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setDescription('Reset platform version to development on a branch via Gitea API');
|
||||
$this->addArgument('--token', 'Gitea API token (also reads MOKOGITEA_TOKEN / GITEA_TOKEN env)', '');
|
||||
$this->addArgument('--api-base', 'Gitea API base URL for the repo', '');
|
||||
$this->setDescription('Reset platform version to development on a branch via Git API');
|
||||
$this->addArgument('--token', 'Git API token (also reads MOKOGIT_TOKEN / GIT_TOKEN env)', '');
|
||||
$this->addArgument('--api-base', 'Git API base URL for the repo', '');
|
||||
$this->addArgument('--branch', 'Target branch (default: dev)', 'dev');
|
||||
$this->addArgument('--platform', 'Platform type: dolibarr, crm-module, joomla, waas-component', '');
|
||||
$this->addArgument('--path', 'Repo root for auto-detecting platform from manifest.xml', '');
|
||||
@@ -41,13 +41,13 @@ class VersionResetDevCli extends CliFramework
|
||||
|
||||
// Allow token from environment
|
||||
if ($token === '') {
|
||||
$envToken = getenv('MOKOGITEA_TOKEN');
|
||||
$envToken = getenv('MOKOGIT_TOKEN');
|
||||
if ($envToken !== false && $envToken !== '') {
|
||||
$token = $envToken;
|
||||
}
|
||||
}
|
||||
if ($token === '') {
|
||||
$envToken = getenv('GITEA_TOKEN');
|
||||
$envToken = getenv('GIT_TOKEN');
|
||||
if ($envToken !== false && $envToken !== '') {
|
||||
$token = $envToken;
|
||||
}
|
||||
@@ -93,7 +93,7 @@ class VersionResetDevCli extends CliFramework
|
||||
private function detectPlatform(string $repoPath): ?string
|
||||
{
|
||||
$root = realpath($repoPath) ?: $repoPath;
|
||||
$manifestXml = "{$root}/.mokogitea/manifest.xml";
|
||||
$manifestXml = "{$root}/.mokogit/manifest.xml";
|
||||
|
||||
if (!file_exists($manifestXml)) {
|
||||
return null;
|
||||
@@ -114,7 +114,7 @@ class VersionResetDevCli extends CliFramework
|
||||
return null;
|
||||
}
|
||||
|
||||
private function giteaApiCall(string $url, string $token, string $method = 'GET', ?string $body = null): ?array
|
||||
private function gitApiCall(string $url, string $token, string $method = 'GET', ?string $body = null): ?array
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
if ($ch === false) {
|
||||
@@ -161,7 +161,7 @@ class VersionResetDevCli extends CliFramework
|
||||
{
|
||||
// Search the repo tree for mod*.class.php files
|
||||
$treeUrl = "{$apiBase}/git/trees/{$branch}?recursive=true";
|
||||
$tree = $this->giteaApiCall($treeUrl, $token);
|
||||
$tree = $this->gitApiCall($treeUrl, $token);
|
||||
|
||||
if ($tree === null || !isset($tree['tree']) || !is_array($tree['tree'])) {
|
||||
$this->log('ERROR', "Could not read repository tree for branch '{$branch}'.");
|
||||
@@ -191,7 +191,7 @@ class VersionResetDevCli extends CliFramework
|
||||
// GET file contents via API
|
||||
$encodedPath = implode('/', array_map('rawurlencode', explode('/', $filePath)));
|
||||
$fileUrl = "{$apiBase}/contents/{$encodedPath}?ref={$branch}";
|
||||
$fileData = $this->giteaApiCall($fileUrl, $token);
|
||||
$fileData = $this->gitApiCall($fileUrl, $token);
|
||||
|
||||
if ($fileData === null || !isset($fileData['content'])) {
|
||||
echo "Skipping {$filePath}: could not fetch contents.\n";
|
||||
@@ -233,7 +233,7 @@ class VersionResetDevCli extends CliFramework
|
||||
]);
|
||||
|
||||
$putUrl = "{$apiBase}/contents/{$encodedPath}";
|
||||
$result = $this->giteaApiCall($putUrl, $token, 'PUT', $putBody);
|
||||
$result = $this->gitApiCall($putUrl, $token, 'PUT', $putBody);
|
||||
|
||||
if ($result !== null) {
|
||||
echo "Reset: {$filePath} -> \$this->version = 'development'\n";
|
||||
|
||||
@@ -80,8 +80,8 @@ class VersionSetPlatformCli extends CliFramework
|
||||
// Detect platform — check manifest.xml first, then legacy .mokostandards
|
||||
$platform = '';
|
||||
|
||||
// New format: .mokogitea/manifest.xml (XML with <platform> tag)
|
||||
$manifestXml = "{$root}/.mokogitea/manifest.xml";
|
||||
// New format: .mokogit/manifest.xml (XML with <platform> tag)
|
||||
$manifestXml = "{$root}/.mokogit/manifest.xml";
|
||||
if (file_exists($manifestXml)) {
|
||||
$xml = @simplexml_load_file($manifestXml);
|
||||
if ($xml && isset($xml->governance->platform)) {
|
||||
@@ -93,7 +93,7 @@ class VersionSetPlatformCli extends CliFramework
|
||||
if (empty($platform)) {
|
||||
$mokoStandards = "{$root}/.github/.mokostandards";
|
||||
if (!file_exists($mokoStandards)) {
|
||||
$mokoStandards = "{$root}/.mokogitea/manifest.xml";
|
||||
$mokoStandards = "{$root}/.mokogit/manifest.xml";
|
||||
}
|
||||
if (!file_exists($mokoStandards)) {
|
||||
$mokoStandards = "{$root}/.mokostandards";
|
||||
|
||||
+4
-4
@@ -22,7 +22,7 @@ use MokoCli\CliFramework;
|
||||
|
||||
class WikiSyncCli extends CliFramework
|
||||
{
|
||||
private string $giteaUrl = 'https://git.mokoconsulting.tech';
|
||||
private string $gitUrl = 'https://git.mokoconsulting.tech';
|
||||
private string $token = '';
|
||||
private string $org = 'MokoConsulting';
|
||||
private string $sourceRepo = 'mokocli';
|
||||
@@ -39,7 +39,7 @@ class WikiSyncCli extends CliFramework
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setDescription('Sync wiki pages from mokocli to template repos');
|
||||
$this->addArgument('--token', 'Gitea API token (required)', '');
|
||||
$this->addArgument('--token', 'Git API token (required)', '');
|
||||
$this->addArgument('--org', 'Organization (default: MokoConsulting)', 'MokoConsulting');
|
||||
$this->addArgument('--source', 'Source repo (default: mokocli)', 'mokocli');
|
||||
$this->addArgument('--target', 'Target repo (can repeat)', '');
|
||||
@@ -195,7 +195,7 @@ class WikiSyncCli extends CliFramework
|
||||
|
||||
private function apiGet(string $endpoint): ?array
|
||||
{
|
||||
$url = "{$this->giteaUrl}/api/v1{$endpoint}";
|
||||
$url = "{$this->gitUrl}/api/v1{$endpoint}";
|
||||
$opts = [
|
||||
'http' => [
|
||||
'method' => 'GET',
|
||||
@@ -224,7 +224,7 @@ class WikiSyncCli extends CliFramework
|
||||
|
||||
private function apiWrite(string $method, string $endpoint, string $payload): ?array
|
||||
{
|
||||
$url = "{$this->giteaUrl}/api/v1{$endpoint}";
|
||||
$url = "{$this->gitUrl}/api/v1{$endpoint}";
|
||||
$opts = [
|
||||
'http' => [
|
||||
'method' => $method,
|
||||
|
||||
+46
-46
@@ -55,8 +55,8 @@ class WorkflowSyncCli extends CliFramework
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setDescription('Sync workflows from Generic → platform templates → live repos based on manifest.platform');
|
||||
$this->addArgument('--gitea-url', 'Gitea URL (default: https://git.mokoconsulting.tech)', 'https://git.mokoconsulting.tech');
|
||||
$this->addArgument('--token', 'Gitea API token', '');
|
||||
$this->addArgument('--git-url', 'Git URL (default: https://git.mokoconsulting.tech)', 'https://git.mokoconsulting.tech');
|
||||
$this->addArgument('--token', 'Git API token', '');
|
||||
$this->addArgument('--org', 'Target organization', '');
|
||||
$this->addArgument('--branch', 'Target branch (default: main)', 'main');
|
||||
$this->addArgument('--phase', 'Phase to run: all, templates, repos (default: all)', 'all');
|
||||
@@ -66,7 +66,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
|
||||
protected function run(): int
|
||||
{
|
||||
$giteaUrl = rtrim($this->getArgument('--gitea-url'), '/');
|
||||
$gitUrl = rtrim($this->getArgument('--git-url'), '/');
|
||||
$token = $this->getArgument('--token');
|
||||
$org = $this->getArgument('--org');
|
||||
$branch = $this->getArgument('--branch');
|
||||
@@ -102,7 +102,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
|
||||
// Phase 1: Sync Generic → Platform Templates
|
||||
if ($phase === 'all' || $phase === 'templates') {
|
||||
$result = $this->syncGenericToTemplates($giteaUrl, $token, $org, $branch, $platformFilter);
|
||||
$result = $this->syncGenericToTemplates($gitUrl, $token, $org, $branch, $platformFilter);
|
||||
|
||||
if ($result !== 0) {
|
||||
return $result;
|
||||
@@ -111,7 +111,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
|
||||
// Phase 2: Sync Platform Templates → Live Repos
|
||||
if ($phase === 'all' || $phase === 'repos') {
|
||||
$result = $this->syncTemplatesToRepos($giteaUrl, $token, $org, $branch, $platformFilter);
|
||||
$result = $this->syncTemplatesToRepos($gitUrl, $token, $org, $branch, $platformFilter);
|
||||
|
||||
if ($result !== 0) {
|
||||
return $result;
|
||||
@@ -130,7 +130,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
* Skips platform-specific overrides (files that exist in the platform template but NOT in Generic).
|
||||
*/
|
||||
private function syncGenericToTemplates(
|
||||
string $giteaUrl,
|
||||
string $gitUrl,
|
||||
string $token,
|
||||
string $org,
|
||||
string $branch,
|
||||
@@ -140,7 +140,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
echo "\n";
|
||||
|
||||
// Get all workflow files from Template-Generic
|
||||
$genericWorkflows = $this->listWorkflows($giteaUrl, $token, $org, self::GENERIC_TEMPLATE, $branch);
|
||||
$genericWorkflows = $this->listWorkflows($gitUrl, $token, $org, self::GENERIC_TEMPLATE, $branch);
|
||||
|
||||
if ($genericWorkflows === null) {
|
||||
$this->log('ERROR', 'Could not list workflows from ' . self::GENERIC_TEMPLATE);
|
||||
@@ -186,12 +186,12 @@ class WorkflowSyncCli extends CliFramework
|
||||
$this->skipped++;
|
||||
continue;
|
||||
}
|
||||
$destPath = '.mokogitea/workflows/' . $filename;
|
||||
$destPath = '.mokogit/workflows/' . $filename;
|
||||
$label = "{$templateRepo}/{$filename}";
|
||||
|
||||
// Get file content from Generic
|
||||
$sourceContent = $this->getFileContent(
|
||||
$giteaUrl, $token, $org,
|
||||
$gitUrl, $token, $org,
|
||||
self::GENERIC_TEMPLATE, $destPath, $branch
|
||||
);
|
||||
|
||||
@@ -204,7 +204,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
$commitMsg = "chore: sync {$filename} from " . self::GENERIC_TEMPLATE . " [skip ci]";
|
||||
|
||||
$this->pushFile(
|
||||
$giteaUrl, $token, $org, $templateRepo,
|
||||
$gitUrl, $token, $org, $templateRepo,
|
||||
$destPath, $sourceContent, $branch, $commitMsg, $label
|
||||
);
|
||||
}
|
||||
@@ -218,7 +218,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
* Phase 2: Sync platform template workflows to live repos based on manifest.platform.
|
||||
*/
|
||||
private function syncTemplatesToRepos(
|
||||
string $giteaUrl,
|
||||
string $gitUrl,
|
||||
string $token,
|
||||
string $org,
|
||||
string $branch,
|
||||
@@ -227,7 +227,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
$this->log('INFO', '=== Phase 2: Sync Platform Templates → Live Repos ===');
|
||||
echo "\n";
|
||||
|
||||
$repos = $this->fetchOrgRepos($giteaUrl, $token, $org);
|
||||
$repos = $this->fetchOrgRepos($gitUrl, $token, $org);
|
||||
|
||||
if ($repos === null) {
|
||||
return 1;
|
||||
@@ -251,7 +251,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
}
|
||||
|
||||
// Read manifest.platform
|
||||
$platform = $this->getRepoPlatform($giteaUrl, $token, $org, $repoName, $branch);
|
||||
$platform = $this->getRepoPlatform($gitUrl, $token, $org, $repoName, $branch);
|
||||
|
||||
// Apply platform filter
|
||||
if ($platformFilter !== '' && $platform !== $platformFilter) {
|
||||
@@ -263,11 +263,11 @@ class WorkflowSyncCli extends CliFramework
|
||||
|
||||
// Get workflows from the template (cached)
|
||||
if (!isset($templateWorkflowCache[$templateRepo])) {
|
||||
$workflows = $this->listWorkflows($giteaUrl, $token, $org, $templateRepo, $branch);
|
||||
$workflows = $this->listWorkflows($gitUrl, $token, $org, $templateRepo, $branch);
|
||||
|
||||
if ($workflows === null) {
|
||||
$this->log('WARN', "Could not list workflows from {$templateRepo}, falling back to " . self::GENERIC_TEMPLATE);
|
||||
$workflows = $this->listWorkflows($giteaUrl, $token, $org, self::GENERIC_TEMPLATE, $branch);
|
||||
$workflows = $this->listWorkflows($gitUrl, $token, $org, self::GENERIC_TEMPLATE, $branch);
|
||||
}
|
||||
|
||||
$templateWorkflowCache[$templateRepo] = $workflows ?? [];
|
||||
@@ -281,7 +281,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
|
||||
foreach ($workflows as $workflow) {
|
||||
$filename = $workflow['name'];
|
||||
$destPath = '.mokogitea/workflows/' . $filename;
|
||||
$destPath = '.mokogit/workflows/' . $filename;
|
||||
$label = "{$repoFullName}/{$filename}";
|
||||
|
||||
// Skip platform-excluded workflows
|
||||
@@ -293,7 +293,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
|
||||
// Get source content from template
|
||||
$sourceContent = $this->getFileContent(
|
||||
$giteaUrl, $token, $org,
|
||||
$gitUrl, $token, $org,
|
||||
$templateRepo, $destPath, $branch
|
||||
);
|
||||
|
||||
@@ -306,7 +306,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
$commitMsg = "chore: sync {$filename} from {$templateRepo} [skip ci]";
|
||||
|
||||
$this->pushFile(
|
||||
$giteaUrl, $token, $org, $repoName,
|
||||
$gitUrl, $token, $org, $repoName,
|
||||
$destPath, $sourceContent, $branch, $commitMsg, $label
|
||||
);
|
||||
}
|
||||
@@ -315,7 +315,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
if ($this->getArgument('--delete-orphans', false)) {
|
||||
$templateNames = array_map(fn($w) => $w['name'], $workflows);
|
||||
$this->deleteOrphanWorkflows(
|
||||
$giteaUrl, $token, $org, $repoName, $branch, $templateNames, $platform
|
||||
$gitUrl, $token, $org, $repoName, $branch, $templateNames, $platform
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -328,7 +328,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
* Push a file to a repo — create or update, skip if identical.
|
||||
*/
|
||||
private function pushFile(
|
||||
string $giteaUrl,
|
||||
string $gitUrl,
|
||||
string $token,
|
||||
string $org,
|
||||
string $repoName,
|
||||
@@ -339,7 +339,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
string $label
|
||||
): void {
|
||||
$existing = $this->apiRequest(
|
||||
$giteaUrl,
|
||||
$gitUrl,
|
||||
$token,
|
||||
'GET',
|
||||
"/api/v1/repos/{$org}/{$repoName}/contents/"
|
||||
@@ -373,7 +373,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
]);
|
||||
|
||||
$response = $this->apiRequest(
|
||||
$giteaUrl,
|
||||
$gitUrl,
|
||||
$token,
|
||||
'PUT',
|
||||
"/api/v1/repos/{$org}/{$repoName}/contents/" . $destPath,
|
||||
@@ -401,7 +401,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
]);
|
||||
|
||||
$response = $this->apiRequest(
|
||||
$giteaUrl,
|
||||
$gitUrl,
|
||||
$token,
|
||||
'POST',
|
||||
"/api/v1/repos/{$org}/{$repoName}/contents/" . $destPath,
|
||||
@@ -431,7 +431,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
* - Platform-excluded workflows
|
||||
*/
|
||||
private function deleteOrphanWorkflows(
|
||||
string $giteaUrl,
|
||||
string $gitUrl,
|
||||
string $token,
|
||||
string $org,
|
||||
string $repoName,
|
||||
@@ -439,7 +439,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
array $templateNames,
|
||||
string $platform
|
||||
): void {
|
||||
$repoWorkflows = $this->listWorkflows($giteaUrl, $token, $org, $repoName, $branch);
|
||||
$repoWorkflows = $this->listWorkflows($gitUrl, $token, $org, $repoName, $branch);
|
||||
if ($repoWorkflows === null) {
|
||||
return;
|
||||
}
|
||||
@@ -469,7 +469,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
}
|
||||
|
||||
// Delete orphan
|
||||
$filePath = '.mokogitea/workflows/' . $name;
|
||||
$filePath = '.mokogit/workflows/' . $name;
|
||||
$label = "{$org}/{$repoName}/{$name}";
|
||||
|
||||
if ($this->dryRun) {
|
||||
@@ -478,7 +478,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
continue;
|
||||
}
|
||||
|
||||
$deleted = $this->deleteFile($giteaUrl, $token, $org, $repoName, $filePath, $branch);
|
||||
$deleted = $this->deleteFile($gitUrl, $token, $org, $repoName, $filePath, $branch);
|
||||
if ($deleted) {
|
||||
fprintf(STDERR, "%-45s | %s\n", $label, 'DELETED');
|
||||
$this->deleted++;
|
||||
@@ -490,10 +490,10 @@ class WorkflowSyncCli extends CliFramework
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a file from a repo via the Gitea Contents API.
|
||||
* Delete a file from a repo via the Git Contents API.
|
||||
*/
|
||||
private function deleteFile(
|
||||
string $giteaUrl,
|
||||
string $gitUrl,
|
||||
string $token,
|
||||
string $org,
|
||||
string $repoName,
|
||||
@@ -502,7 +502,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
): bool {
|
||||
// Get SHA first
|
||||
$existing = $this->apiRequest(
|
||||
$giteaUrl, $token, 'GET',
|
||||
$gitUrl, $token, 'GET',
|
||||
"/api/v1/repos/{$org}/{$repoName}/contents/{$filePath}?ref={$branch}"
|
||||
);
|
||||
|
||||
@@ -523,7 +523,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
]);
|
||||
|
||||
$response = $this->apiRequest(
|
||||
$giteaUrl, $token, 'DELETE',
|
||||
$gitUrl, $token, 'DELETE',
|
||||
"/api/v1/repos/{$org}/{$repoName}/contents/{$filePath}",
|
||||
$payload
|
||||
);
|
||||
@@ -532,20 +532,20 @@ class WorkflowSyncCli extends CliFramework
|
||||
}
|
||||
|
||||
/**
|
||||
* List workflow files in a repo's .mokogitea/workflows/ directory.
|
||||
* List workflow files in a repo's .mokogit/workflows/ directory.
|
||||
*/
|
||||
private function listWorkflows(
|
||||
string $giteaUrl,
|
||||
string $gitUrl,
|
||||
string $token,
|
||||
string $org,
|
||||
string $repoName,
|
||||
string $branch
|
||||
): ?array {
|
||||
$response = $this->apiRequest(
|
||||
$giteaUrl,
|
||||
$gitUrl,
|
||||
$token,
|
||||
'GET',
|
||||
"/api/v1/repos/{$org}/{$repoName}/contents/.mokogitea/workflows?ref={$branch}"
|
||||
"/api/v1/repos/{$org}/{$repoName}/contents/.mokogit/workflows?ref={$branch}"
|
||||
);
|
||||
|
||||
if ($response['code'] !== 200) {
|
||||
@@ -566,7 +566,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
* Get file content from a repo as a raw string.
|
||||
*/
|
||||
private function getFileContent(
|
||||
string $giteaUrl,
|
||||
string $gitUrl,
|
||||
string $token,
|
||||
string $org,
|
||||
string $repoName,
|
||||
@@ -574,7 +574,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
string $branch
|
||||
): ?string {
|
||||
$response = $this->apiRequest(
|
||||
$giteaUrl,
|
||||
$gitUrl,
|
||||
$token,
|
||||
'GET',
|
||||
"/api/v1/repos/{$org}/{$repoName}/contents/{$filePath}?ref={$branch}"
|
||||
@@ -594,20 +594,20 @@ class WorkflowSyncCli extends CliFramework
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a repo's platform from the MokoGitea metadata API.
|
||||
* Read a repo's platform from the MokoGit metadata API.
|
||||
* Returns 'generic' if metadata is missing or has no platform field.
|
||||
* (Replaces the retired .mokogitea/manifest.xml lookup — platform now lives
|
||||
* (Replaces the retired .mokogit/manifest.xml lookup — platform now lives
|
||||
* in the repo Metadata endpoint: GET /api/v1/repos/{owner}/{repo}/metadata.)
|
||||
*/
|
||||
private function getRepoPlatform(
|
||||
string $giteaUrl,
|
||||
string $gitUrl,
|
||||
string $token,
|
||||
string $org,
|
||||
string $repoName,
|
||||
string $branch
|
||||
): string {
|
||||
$response = $this->apiRequest(
|
||||
$giteaUrl,
|
||||
$gitUrl,
|
||||
$token,
|
||||
'GET',
|
||||
"/api/v1/repos/{$org}/{$repoName}/metadata"
|
||||
@@ -629,7 +629,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
/**
|
||||
* Fetch all non-archived repos in an org (paginated).
|
||||
*/
|
||||
private function fetchOrgRepos(string $giteaUrl, string $token, string $org): ?array
|
||||
private function fetchOrgRepos(string $gitUrl, string $token, string $org): ?array
|
||||
{
|
||||
$this->log('INFO', "Fetching repos from org: {$org}");
|
||||
|
||||
@@ -638,7 +638,7 @@ class WorkflowSyncCli extends CliFramework
|
||||
|
||||
while (true) {
|
||||
$response = $this->apiRequest(
|
||||
$giteaUrl,
|
||||
$gitUrl,
|
||||
$token,
|
||||
'GET',
|
||||
"/api/v1/orgs/{$org}/repos?"
|
||||
@@ -680,16 +680,16 @@ class WorkflowSyncCli extends CliFramework
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an HTTP request to the Gitea API.
|
||||
* Make an HTTP request to the Git API.
|
||||
*/
|
||||
private function apiRequest(
|
||||
string $giteaUrl,
|
||||
string $gitUrl,
|
||||
string $token,
|
||||
string $method,
|
||||
string $endpoint,
|
||||
?string $body = null
|
||||
): array {
|
||||
$url = $giteaUrl . $endpoint;
|
||||
$url = $gitUrl . $endpoint;
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
|
||||
@@ -61,7 +61,7 @@ Shared library code
|
||||
- GitHub client
|
||||
|
||||
### [Wiki](https://git.mokoconsulting.tech/MokoConsulting/mokocli/wiki)
|
||||
All documentation lives in the MokoGitea wiki.
|
||||
All documentation lives in the MokoGit wiki.
|
||||
|
||||
### [Tests](tests/)
|
||||
Test scripts
|
||||
|
||||
@@ -154,7 +154,7 @@ class ApiClient
|
||||
* @param bool $enableCaching Enable response caching
|
||||
* @param string $userAgent User agent string
|
||||
* @param LoggerInterface|null $logger Optional logger
|
||||
* @param string $authScheme Authorization scheme ('Bearer' for GitHub, 'token' for Gitea)
|
||||
* @param string $authScheme Authorization scheme ('Bearer' for GitHub, 'token' for Git)
|
||||
*/
|
||||
public function __construct(
|
||||
string $baseUrl,
|
||||
|
||||
+10
-10
@@ -74,14 +74,14 @@ class Config
|
||||
private const DEFAULT_CONFIG = [
|
||||
'version' => '04.00.04',
|
||||
'environment' => 'development',
|
||||
'platform' => 'gitea',
|
||||
'platform' => 'git',
|
||||
'github' => [
|
||||
'organization' => 'mokoconsulting-tech',
|
||||
'rate_limit' => 5000,
|
||||
'max_retries' => 3,
|
||||
'timeout' => 30,
|
||||
],
|
||||
'gitea' => [
|
||||
'git' => [
|
||||
'url' => 'https://git.mokoconsulting.tech',
|
||||
'organization' => 'mokoconsulting-tech',
|
||||
'rate_limit' => 5000,
|
||||
@@ -227,16 +227,16 @@ class Config
|
||||
$configData['github']['organization'] = $org;
|
||||
}
|
||||
|
||||
// Gitea token resolution: GA_TOKEN env var (Gitea Actions)
|
||||
$giteaToken = getenv('GA_TOKEN') ?: '';
|
||||
if (!empty($giteaToken)) {
|
||||
$configData['gitea']['token'] = $giteaToken;
|
||||
// Git token resolution: GA_TOKEN env var (Git Actions)
|
||||
$gitToken = getenv('GA_TOKEN') ?: '';
|
||||
if (!empty($gitToken)) {
|
||||
$configData['git']['token'] = $gitToken;
|
||||
}
|
||||
if ($giteaUrl = getenv('GITEA_URL')) {
|
||||
$configData['gitea']['url'] = rtrim($giteaUrl, '/');
|
||||
if ($gitUrl = getenv('GIT_URL')) {
|
||||
$configData['git']['url'] = rtrim($gitUrl, '/');
|
||||
}
|
||||
if ($giteaOrg = getenv('GITEA_ORG')) {
|
||||
$configData['gitea']['organization'] = $giteaOrg;
|
||||
if ($gitOrg = getenv('GIT_ORG')) {
|
||||
$configData['git']['organization'] = $gitOrg;
|
||||
}
|
||||
|
||||
// Logging configuration
|
||||
|
||||
@@ -419,7 +419,7 @@ class GitHubAdapter implements GitPlatformAdapter
|
||||
|
||||
public function migrateRepository(array $options): array
|
||||
{
|
||||
throw new RuntimeException('Repository migration is not supported on GitHub — use Gitea\'s built-in migration');
|
||||
throw new RuntimeException('Repository migration is not supported on GitHub — use Git\'s built-in migration');
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* INGROUP: MokoCLI.Enterprise
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /lib/Enterprise/GitPlatformAdapter.php
|
||||
* BRIEF: Interface defining all git platform operations for GitHub/Gitea abstraction
|
||||
* BRIEF: Interface defining all git platform operations for GitHub/Git abstraction
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
@@ -22,7 +22,7 @@ namespace MokoCli;
|
||||
* Git Platform Adapter Interface
|
||||
*
|
||||
* Defines all platform operations required by mokocli automation.
|
||||
* Implementations exist for GitHub (GitHubAdapter) and Gitea (MokoGiteaAdapter),
|
||||
* Implementations exist for GitHub (GitHubAdapter) and Git (MokoGitAdapter),
|
||||
* allowing scripts to work against either platform transparently.
|
||||
*
|
||||
* @package MokoCLI\Enterprise
|
||||
@@ -37,7 +37,7 @@ interface GitPlatformAdapter
|
||||
/**
|
||||
* Get the platform name identifier.
|
||||
*
|
||||
* @return string 'github' or 'gitea'
|
||||
* @return string 'github' or 'git'
|
||||
*/
|
||||
public function getPlatformName(): string;
|
||||
|
||||
@@ -51,14 +51,14 @@ interface GitPlatformAdapter
|
||||
/**
|
||||
* Get the workflow directory name for this platform.
|
||||
*
|
||||
* @return string '.github/workflows' or '.mokogitea/workflows'
|
||||
* @return string '.github/workflows' or '.mokogit/workflows'
|
||||
*/
|
||||
public function getWorkflowDir(): string;
|
||||
|
||||
/**
|
||||
* Get the platform-specific metadata directory.
|
||||
*
|
||||
* @return string '.github' or '.mokogitea'
|
||||
* @return string '.github' or '.mokogit'
|
||||
*/
|
||||
public function getMetadataDir(): string;
|
||||
|
||||
@@ -104,7 +104,7 @@ interface GitPlatformAdapter
|
||||
/**
|
||||
* Get the environment variable name for step summary output (CI-specific).
|
||||
*
|
||||
* @return string 'GITHUB_STEP_SUMMARY' or 'GITEA_STEP_SUMMARY'
|
||||
* @return string 'GITHUB_STEP_SUMMARY' or 'GIT_STEP_SUMMARY'
|
||||
*/
|
||||
public function getStepSummaryEnvVar(): string;
|
||||
|
||||
@@ -379,7 +379,7 @@ interface GitPlatformAdapter
|
||||
* @param string $org Organization name
|
||||
* @param string $repo Repository name
|
||||
* @param int $number Issue/PR number
|
||||
* @param array<string> $labels Label names (GitHub) or label IDs (Gitea)
|
||||
* @param array<string> $labels Label names (GitHub) or label IDs (Git)
|
||||
* @return array<string, mixed> API response
|
||||
*/
|
||||
public function addIssueLabels(string $org, string $repo, int $number, array $labels): array;
|
||||
@@ -391,7 +391,7 @@ interface GitPlatformAdapter
|
||||
/**
|
||||
* Set branch protection rules.
|
||||
*
|
||||
* On GitHub this maps to rulesets; on Gitea to branch_protections.
|
||||
* On GitHub this maps to rulesets; on Git to branch_protections.
|
||||
*
|
||||
* @param string $org Organization name
|
||||
* @param string $repo Repository name
|
||||
@@ -450,13 +450,13 @@ interface GitPlatformAdapter
|
||||
public function paginateAll(string $endpoint, array $params = [], int $perPage = 100): array;
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// Migration (Gitea-specific, no-op on GitHub)
|
||||
// Migration (Git-specific, no-op on GitHub)
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Migrate a repository from an external service.
|
||||
*
|
||||
* On Gitea, this calls POST /api/v1/repos/migrate.
|
||||
* On Git, this calls POST /api/v1/repos/migrate.
|
||||
* On GitHub, this is a no-op (throws UnsupportedOperationException).
|
||||
*
|
||||
* @param array<string, mixed> $options Migration options (clone_addr, service, auth_token, etc.)
|
||||
|
||||
@@ -26,7 +26,7 @@ use SimpleXMLElement;
|
||||
* MokoCli Parser
|
||||
*
|
||||
* Reads, writes, and validates the manifest.xml repository manifest.
|
||||
* The file uses XML format (no file extension) and lives at .mokogitea/manifest.xml.
|
||||
* The file uses XML format (no file extension) and lives at .mokogit/manifest.xml.
|
||||
*
|
||||
* @package MokoCLI\Enterprise
|
||||
* @version 04.07.00
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /lib/Enterprise/ManifestReader.php
|
||||
* BRIEF: Read and parse .mokogitea/manifest.xml — shared across all CLI tools
|
||||
* BRIEF: Read and parse .mokogit/manifest.xml — shared across all CLI tools
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
@@ -21,7 +21,7 @@ namespace MokoCli;
|
||||
/**
|
||||
* Manifest Reader
|
||||
*
|
||||
* Parses .mokogitea/manifest.xml and provides typed access to all fields.
|
||||
* Parses .mokogit/manifest.xml and provides typed access to all fields.
|
||||
* Used by CLI tools and the Enterprise library to determine platform,
|
||||
* build configuration, and deployment settings from the repository manifest.
|
||||
*
|
||||
@@ -56,9 +56,9 @@ class ManifestReader
|
||||
public function load(string $root): void
|
||||
{
|
||||
$candidates = [
|
||||
"{$root}/.mokogitea/manifest.xml",
|
||||
"{$root}/.mokogitea/.manifest.xml",
|
||||
"{$root}/.mokogitea/.mokocli",
|
||||
"{$root}/.mokogit/manifest.xml",
|
||||
"{$root}/.mokogit/.manifest.xml",
|
||||
"{$root}/.mokogit/.mokocli",
|
||||
];
|
||||
|
||||
$manifestFile = null;
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
* DEFGROUP: MokoCLI.Enterprise.Platform
|
||||
* INGROUP: MokoCLI.Enterprise
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /lib/Enterprise/MokoGiteaAdapter.php
|
||||
* BRIEF: Gitea implementation of GitPlatformAdapter
|
||||
* PATH: /lib/Enterprise/MokoGitAdapter.php
|
||||
* BRIEF: Git implementation of GitPlatformAdapter
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
@@ -22,32 +22,32 @@ use Exception;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Gitea implementation of GitPlatformAdapter.
|
||||
* Git implementation of GitPlatformAdapter.
|
||||
*
|
||||
* Wraps ApiClient with Gitea-specific API semantics:
|
||||
* Wraps ApiClient with Git-specific API semantics:
|
||||
* - Base URL: https://git.mokoconsulting.tech/api/v1
|
||||
* - Auth: token {token}
|
||||
* - Pagination: limit + page params
|
||||
* - File ops: POST for create, PUT for update (check existence first)
|
||||
* - Topics: PUT with {"topics": [...]}
|
||||
* - Branch protection: flat API (not rulesets)
|
||||
* - Workflow dir: .mokogitea/workflows
|
||||
* - Workflow dir: .mokogit/workflows
|
||||
*
|
||||
* @package MokoCLI\Enterprise
|
||||
* @since 04.06.10
|
||||
* @see GitPlatformAdapter
|
||||
*/
|
||||
class MokoGiteaAdapter implements GitPlatformAdapter
|
||||
class MokoGitAdapter implements GitPlatformAdapter
|
||||
{
|
||||
/** @var ApiClient HTTP client for Gitea API calls. */
|
||||
/** @var ApiClient HTTP client for Git API calls. */
|
||||
private ApiClient $apiClient;
|
||||
|
||||
/** @var string Base URL for Gitea API (e.g. https://git.mokoconsulting.tech/api/v1). */
|
||||
/** @var string Base URL for Git API (e.g. https://git.mokoconsulting.tech/api/v1). */
|
||||
private string $baseUrl;
|
||||
|
||||
/**
|
||||
* @param ApiClient $apiClient Configured API client
|
||||
* @param string $baseUrl Gitea API base URL
|
||||
* @param string $baseUrl Git API base URL
|
||||
*/
|
||||
public function __construct(ApiClient $apiClient, string $baseUrl = 'https://git.mokoconsulting.tech/api/v1')
|
||||
{
|
||||
@@ -61,7 +61,7 @@ class MokoGiteaAdapter implements GitPlatformAdapter
|
||||
|
||||
public function getPlatformName(): string
|
||||
{
|
||||
return 'gitea';
|
||||
return 'git';
|
||||
}
|
||||
|
||||
public function getBaseUrl(): string
|
||||
@@ -71,12 +71,12 @@ class MokoGiteaAdapter implements GitPlatformAdapter
|
||||
|
||||
public function getWorkflowDir(): string
|
||||
{
|
||||
return '.mokogitea/workflows';
|
||||
return '.mokogit/workflows';
|
||||
}
|
||||
|
||||
public function getMetadataDir(): string
|
||||
{
|
||||
return '.mokogitea';
|
||||
return '.mokogit';
|
||||
}
|
||||
|
||||
public function getRepoWebUrl(string $org, string $repo): string
|
||||
@@ -88,7 +88,7 @@ class MokoGiteaAdapter implements GitPlatformAdapter
|
||||
|
||||
public function getPullRequestWebUrl(string $org, string $repo, int $number): string
|
||||
{
|
||||
// Gitea uses /pulls/ (not /pull/) for web UI
|
||||
// Git uses /pulls/ (not /pull/) for web UI
|
||||
$webBase = preg_replace('#/api/v1$#', '', $this->baseUrl);
|
||||
return "{$webBase}/{$org}/{$repo}/pulls/{$number}";
|
||||
}
|
||||
@@ -106,14 +106,14 @@ class MokoGiteaAdapter implements GitPlatformAdapter
|
||||
|
||||
public function getBranchWebUrl(string $org, string $repo, string $branch): string
|
||||
{
|
||||
// Gitea uses /src/branch/ (not /tree/) for web UI
|
||||
// Git uses /src/branch/ (not /tree/) for web UI
|
||||
$webBase = preg_replace('#/api/v1$#', '', $this->baseUrl);
|
||||
return "{$webBase}/{$org}/{$repo}/src/branch/{$branch}";
|
||||
}
|
||||
|
||||
public function getStepSummaryEnvVar(): string
|
||||
{
|
||||
return 'GITEA_STEP_SUMMARY';
|
||||
return 'GIT_STEP_SUMMARY';
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
@@ -157,7 +157,7 @@ class MokoGiteaAdapter implements GitPlatformAdapter
|
||||
|
||||
public function archiveRepo(string $org, string $repo): array
|
||||
{
|
||||
// Gitea uses PATCH with archived flag, same as GitHub
|
||||
// Git uses PATCH with archived flag, same as GitHub
|
||||
return $this->apiClient->patch("/repos/{$org}/{$repo}", [
|
||||
'archived' => true,
|
||||
]);
|
||||
@@ -165,7 +165,7 @@ class MokoGiteaAdapter implements GitPlatformAdapter
|
||||
|
||||
public function setRepoTopics(string $org, string $repo, array $topics): void
|
||||
{
|
||||
// Gitea uses {"topics": [...]} not {"names": [...]}
|
||||
// Git uses {"topics": [...]} not {"names": [...]}
|
||||
$this->apiClient->put("/repos/{$org}/{$repo}/topics", [
|
||||
'topics' => $topics,
|
||||
]);
|
||||
@@ -209,12 +209,12 @@ class MokoGiteaAdapter implements GitPlatformAdapter
|
||||
}
|
||||
|
||||
if ($sha !== null) {
|
||||
// Update existing file — Gitea uses PUT with SHA
|
||||
// Update existing file — Git uses PUT with SHA
|
||||
$data['sha'] = $sha;
|
||||
return $this->apiClient->put("/repos/{$org}/{$repo}/contents/{$path}", $data);
|
||||
}
|
||||
|
||||
// Create new file — Gitea uses POST
|
||||
// Create new file — Git uses POST
|
||||
return $this->apiClient->post("/repos/{$org}/{$repo}/contents/{$path}", $data);
|
||||
}
|
||||
|
||||
@@ -226,7 +226,7 @@ class MokoGiteaAdapter implements GitPlatformAdapter
|
||||
string $message,
|
||||
?string $branch = null
|
||||
): array {
|
||||
// Gitea's delete uses the same endpoint but with DELETE method
|
||||
// Git's delete uses the same endpoint but with DELETE method
|
||||
// ApiClient::delete() doesn't support a body, so we use the raw approach
|
||||
// For now, this matches GitHubAdapter's limitation
|
||||
return $this->apiClient->delete("/repos/{$org}/{$repo}/contents/{$path}");
|
||||
@@ -281,7 +281,7 @@ class MokoGiteaAdapter implements GitPlatformAdapter
|
||||
string $body = '',
|
||||
array $options = []
|
||||
): array {
|
||||
// Gitea expects label IDs (int64), not names. Resolve if needed.
|
||||
// Git expects label IDs (int64), not names. Resolve if needed.
|
||||
if (!empty($options['labels']) && is_string($options['labels'][0] ?? null)) {
|
||||
$labelNames = $options['labels'];
|
||||
$existing = $this->listLabels($org, $repo);
|
||||
@@ -330,7 +330,7 @@ class MokoGiteaAdapter implements GitPlatformAdapter
|
||||
|
||||
public function createLabel(string $org, string $repo, string $name, string $color, string $description = ''): array
|
||||
{
|
||||
// Gitea expects color with # prefix
|
||||
// Git expects color with # prefix
|
||||
$color = ltrim($color, '#');
|
||||
return $this->apiClient->post("/repos/{$org}/{$repo}/labels", [
|
||||
'name' => $name,
|
||||
@@ -341,7 +341,7 @@ class MokoGiteaAdapter implements GitPlatformAdapter
|
||||
|
||||
public function addIssueLabels(string $org, string $repo, int $number, array $labels): array
|
||||
{
|
||||
// Gitea requires label IDs, not names. Resolve names to IDs first.
|
||||
// Git requires label IDs, not names. Resolve names to IDs first.
|
||||
$allLabels = $this->listLabels($org, $repo);
|
||||
$labelMap = [];
|
||||
foreach ($allLabels as $label) {
|
||||
@@ -372,7 +372,7 @@ class MokoGiteaAdapter implements GitPlatformAdapter
|
||||
|
||||
public function setBranchProtection(string $org, string $repo, string $branch, array $rules): array
|
||||
{
|
||||
// Gitea uses a flat branch protection API
|
||||
// Git uses a flat branch protection API
|
||||
$whitelistActions = $rules['whitelist_actions_user'] ?? false;
|
||||
$protection = [
|
||||
'branch_name' => $branch,
|
||||
@@ -421,7 +421,7 @@ class MokoGiteaAdapter implements GitPlatformAdapter
|
||||
// Try as a tag first
|
||||
try {
|
||||
$tag = $this->apiClient->get("/repos/{$org}/{$repo}/git/tags/{$ref}");
|
||||
// Gitea tag objects have a 'commit' field with the SHA
|
||||
// Git tag objects have a 'commit' field with the SHA
|
||||
if (isset($tag['commit']['sha'])) {
|
||||
return $tag['commit']['sha'];
|
||||
}
|
||||
@@ -458,7 +458,7 @@ class MokoGiteaAdapter implements GitPlatformAdapter
|
||||
{
|
||||
$all = [];
|
||||
$page = 1;
|
||||
// Gitea uses 'limit' instead of 'per_page'
|
||||
// Git uses 'limit' instead of 'per_page'
|
||||
$params['limit'] = $perPage;
|
||||
|
||||
while (true) {
|
||||
@@ -488,7 +488,7 @@ class MokoGiteaAdapter implements GitPlatformAdapter
|
||||
|
||||
public function migrateRepository(array $options): array
|
||||
{
|
||||
// Gitea's built-in migration endpoint
|
||||
// Git's built-in migration endpoint
|
||||
$data = array_merge([
|
||||
'service' => 'github',
|
||||
'issues' => true,
|
||||
|
||||
@@ -44,18 +44,18 @@ class PlatformAdapterFactory
|
||||
* Create a GitPlatformAdapter based on configuration.
|
||||
*
|
||||
* @param Config $config Configuration instance
|
||||
* @param string|null $platformOverride Force a specific platform ('github' or 'gitea')
|
||||
* @param string|null $platformOverride Force a specific platform ('github' or 'git')
|
||||
* @return GitPlatformAdapter The constructed adapter
|
||||
* @throws RuntimeException If the platform is not supported or token is missing
|
||||
*/
|
||||
public static function create(Config $config, ?string $platformOverride = null): GitPlatformAdapter
|
||||
{
|
||||
$platform = $platformOverride ?? $config->getString('platform', 'gitea');
|
||||
$platform = $platformOverride ?? $config->getString('platform', 'git');
|
||||
|
||||
return match ($platform) {
|
||||
'github' => self::createGitHubAdapter($config),
|
||||
'gitea' => self::createMokoGiteaAdapter($config),
|
||||
default => throw new RuntimeException("Unsupported git platform: {$platform}. Use 'github' or 'gitea'."),
|
||||
'git' => self::createMokoGitAdapter($config),
|
||||
default => throw new RuntimeException("Unsupported git platform: {$platform}. Use 'github' or 'git'."),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -87,54 +87,54 @@ class PlatformAdapterFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a MokoGiteaAdapter with configured ApiClient.
|
||||
* Create a MokoGitAdapter with configured ApiClient.
|
||||
*
|
||||
* @param Config $config Configuration instance
|
||||
* @return MokoGiteaAdapter Configured Gitea adapter
|
||||
* @throws RuntimeException If Gitea token is not available
|
||||
* @return MokoGitAdapter Configured Git adapter
|
||||
* @throws RuntimeException If Git token is not available
|
||||
*/
|
||||
private static function createMokoGiteaAdapter(Config $config): MokoGiteaAdapter
|
||||
private static function createMokoGitAdapter(Config $config): MokoGitAdapter
|
||||
{
|
||||
$token = $config->getString('gitea.token', '');
|
||||
$token = $config->getString('git.token', '');
|
||||
if (empty($token)) {
|
||||
throw new RuntimeException(
|
||||
'Gitea token not found. Set GA_TOKEN environment variable.'
|
||||
'Git token not found. Set GA_TOKEN environment variable.'
|
||||
);
|
||||
}
|
||||
|
||||
$giteaUrl = $config->getString('gitea.url', 'https://git.mokoconsulting.tech');
|
||||
$apiBaseUrl = rtrim($giteaUrl, '/') . '/api/v1';
|
||||
$gitUrl = $config->getString('git.url', 'https://git.mokoconsulting.tech');
|
||||
$apiBaseUrl = rtrim($gitUrl, '/') . '/api/v1';
|
||||
|
||||
$apiClient = new ApiClient(
|
||||
baseUrl: $apiBaseUrl,
|
||||
authToken: $token,
|
||||
maxRequestsPerHour: $config->getInt('gitea.rate_limit', 5000),
|
||||
maxRetries: $config->getInt('gitea.max_retries', 3),
|
||||
maxRequestsPerHour: $config->getInt('git.rate_limit', 5000),
|
||||
maxRetries: $config->getInt('git.max_retries', 3),
|
||||
authScheme: 'token'
|
||||
);
|
||||
|
||||
return new MokoGiteaAdapter($apiClient, $apiBaseUrl);
|
||||
return new MokoGitAdapter($apiClient, $apiBaseUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create adapters for both platforms (useful during migration).
|
||||
*
|
||||
* @param Config $config Configuration instance
|
||||
* @return array{github: GitHubAdapter, gitea: MokoGiteaAdapter} Both adapters
|
||||
* @return array{github: GitHubAdapter, git: MokoGitAdapter} Both adapters
|
||||
* @throws RuntimeException If either token is missing
|
||||
*/
|
||||
public static function createBoth(Config $config): array
|
||||
{
|
||||
return [
|
||||
'github' => self::createGitHubAdapter($config),
|
||||
'gitea' => self::createMokoGiteaAdapter($config),
|
||||
'git' => self::createMokoGitAdapter($config),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync a file between Gitea (primary) and GitHub (mirror) for a given repo.
|
||||
* Sync a file between Git (primary) and GitHub (mirror) for a given repo.
|
||||
*
|
||||
* Reads the file from Gitea and pushes it to GitHub, ensuring both platforms
|
||||
* Reads the file from Git and pushes it to GitHub, ensuring both platforms
|
||||
* serve identical content. Commonly used for updates.xml sync after releases.
|
||||
*
|
||||
* @param Config $config Configuration instance
|
||||
@@ -151,18 +151,18 @@ class PlatformAdapterFactory
|
||||
string $filePath = 'updates.xml'
|
||||
): bool {
|
||||
$adapters = self::createBoth($config);
|
||||
$giteaOrg = $config->getString('gitea.organization', 'mokoconsulting-tech');
|
||||
$gitOrg = $config->getString('git.organization', 'mokoconsulting-tech');
|
||||
$githubOrg = $config->getString('github.organization', 'mokoconsulting-tech');
|
||||
|
||||
// Read from Gitea (primary)
|
||||
// Read from Git (primary)
|
||||
try {
|
||||
$giteaFile = $adapters['gitea']->getFileContents($giteaOrg, $repo, $filePath, $branch);
|
||||
$gitFile = $adapters['git']->getFileContents($gitOrg, $repo, $filePath, $branch);
|
||||
} catch (\Exception $e) {
|
||||
throw new RuntimeException("Failed to read {$filePath} from Gitea ({$giteaOrg}/{$repo}): " . $e->getMessage());
|
||||
throw new RuntimeException("Failed to read {$filePath} from Git ({$gitOrg}/{$repo}): " . $e->getMessage());
|
||||
}
|
||||
|
||||
$giteaContent = base64_decode($giteaFile['content'] ?? '');
|
||||
if (empty($giteaContent)) {
|
||||
$gitContent = base64_decode($gitFile['content'] ?? '');
|
||||
if (empty($gitContent)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ class PlatformAdapterFactory
|
||||
$githubContent = base64_decode($githubFile['content'] ?? '');
|
||||
$githubSha = $githubFile['sha'] ?? null;
|
||||
|
||||
if ($githubContent === $giteaContent) {
|
||||
if ($githubContent === $gitContent) {
|
||||
return true;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
@@ -184,8 +184,8 @@ class PlatformAdapterFactory
|
||||
$githubOrg,
|
||||
$repo,
|
||||
$filePath,
|
||||
$giteaContent,
|
||||
"chore(sync): sync {$filePath} from Gitea primary",
|
||||
$gitContent,
|
||||
"chore(sync): sync {$filePath} from Git primary",
|
||||
$githubSha,
|
||||
$branch
|
||||
);
|
||||
|
||||
@@ -288,7 +288,7 @@ class ApiPlugin extends AbstractProjectPlugin
|
||||
'docker-compose.yml',
|
||||
'kubernetes/*.yaml',
|
||||
'tests/ or test/',
|
||||
'.mokogitea/workflows/* or .gitea/workflows/* or .gitlab-ci.yml',
|
||||
'.mokogit/workflows/* or .gitea/workflows/* or .gitlab-ci.yml',
|
||||
'middleware/ or middlewares/',
|
||||
];
|
||||
}
|
||||
@@ -696,8 +696,8 @@ class ApiPlugin extends AbstractProjectPlugin
|
||||
*/
|
||||
private function hasCICD(string $projectPath): bool
|
||||
{
|
||||
return $this->fileExists($projectPath, '.mokogitea/workflows') ||
|
||||
$this->fileExists($projectPath, '.mokogitea/workflows') ||
|
||||
return $this->fileExists($projectPath, '.mokogit/workflows') ||
|
||||
$this->fileExists($projectPath, '.mokogit/workflows') ||
|
||||
$this->fileExists($projectPath, '.gitlab-ci.yml') ||
|
||||
$this->fileExists($projectPath, 'Jenkinsfile') ||
|
||||
$this->fileExists($projectPath, '.circleci');
|
||||
|
||||
@@ -80,8 +80,8 @@ class GenericPlugin extends AbstractProjectPlugin
|
||||
}
|
||||
|
||||
// Check for CI/CD configuration
|
||||
$hasCICD = $this->fileExists($projectPath, '.mokogitea/workflows') ||
|
||||
$this->fileExists($projectPath, '.mokogitea/workflows') ||
|
||||
$hasCICD = $this->fileExists($projectPath, '.mokogit/workflows') ||
|
||||
$this->fileExists($projectPath, '.mokogit/workflows') ||
|
||||
$this->fileExists($projectPath, '.gitlab-ci.yml') ||
|
||||
$this->fileExists($projectPath, '.travis.yml') ||
|
||||
$this->fileExists($projectPath, 'Jenkinsfile') ||
|
||||
@@ -288,7 +288,7 @@ class GenericPlugin extends AbstractProjectPlugin
|
||||
'CONTRIBUTING.md',
|
||||
'CODE_OF_CONDUCT.md',
|
||||
'SECURITY.md',
|
||||
'.mokogitea/workflows/* or .gitea/workflows/* or .gitlab-ci.yml',
|
||||
'.mokogit/workflows/* or .gitea/workflows/* or .gitlab-ci.yml',
|
||||
'docs/ or documentation/',
|
||||
'tests/ or test/',
|
||||
];
|
||||
@@ -372,8 +372,8 @@ class GenericPlugin extends AbstractProjectPlugin
|
||||
*/
|
||||
private function hasCICD(string $projectPath): bool
|
||||
{
|
||||
return $this->fileExists($projectPath, '.mokogitea/workflows') ||
|
||||
$this->fileExists($projectPath, '.mokogitea/workflows') ||
|
||||
return $this->fileExists($projectPath, '.mokogit/workflows') ||
|
||||
$this->fileExists($projectPath, '.mokogit/workflows') ||
|
||||
$this->fileExists($projectPath, '.gitlab-ci.yml') ||
|
||||
$this->fileExists($projectPath, '.travis.yml') ||
|
||||
$this->fileExists($projectPath, 'Jenkinsfile') ||
|
||||
|
||||
@@ -344,7 +344,7 @@ class MobilePlugin extends AbstractProjectPlugin
|
||||
'App icons for all required sizes',
|
||||
'Splash screen assets',
|
||||
'tests/ or __tests__/',
|
||||
'.mokogitea/workflows/* or .gitea/workflows/* or fastlane/',
|
||||
'.mokogit/workflows/* or .gitea/workflows/* or fastlane/',
|
||||
'React Native: metro.config.js',
|
||||
'Flutter: analysis_options.yaml',
|
||||
'iOS: Podfile',
|
||||
@@ -551,8 +551,8 @@ class MobilePlugin extends AbstractProjectPlugin
|
||||
*/
|
||||
private function hasCICD(string $projectPath): bool
|
||||
{
|
||||
return $this->fileExists($projectPath, '.mokogitea/workflows') ||
|
||||
$this->fileExists($projectPath, '.mokogitea/workflows') ||
|
||||
return $this->fileExists($projectPath, '.mokogit/workflows') ||
|
||||
$this->fileExists($projectPath, '.mokogit/workflows') ||
|
||||
$this->fileExists($projectPath, '.gitlab-ci.yml') ||
|
||||
$this->fileExists($projectPath, 'fastlane') ||
|
||||
$this->fileExists($projectPath, '.circleci');
|
||||
|
||||
@@ -327,7 +327,7 @@ class NodeJsPlugin extends AbstractProjectPlugin
|
||||
'.nvmrc or .node-version',
|
||||
'.editorconfig',
|
||||
'jest.config.js or vitest.config.js',
|
||||
'.mokogitea/workflows/* or .gitea/workflows/* or .gitlab-ci.yml',
|
||||
'.mokogit/workflows/* or .gitea/workflows/* or .gitlab-ci.yml',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -539,8 +539,8 @@ class NodeJsPlugin extends AbstractProjectPlugin
|
||||
*/
|
||||
private function hasCICD(string $projectPath): bool
|
||||
{
|
||||
return $this->fileExists($projectPath, '.mokogitea/workflows') ||
|
||||
$this->fileExists($projectPath, '.mokogitea/workflows') ||
|
||||
return $this->fileExists($projectPath, '.mokogit/workflows') ||
|
||||
$this->fileExists($projectPath, '.mokogit/workflows') ||
|
||||
$this->fileExists($projectPath, '.gitlab-ci.yml') ||
|
||||
$this->fileExists($projectPath, '.travis.yml') ||
|
||||
$this->fileExists($projectPath, '.circleci/config.yml');
|
||||
|
||||
@@ -344,7 +344,7 @@ class PythonPlugin extends AbstractProjectPlugin
|
||||
'pytest.ini or pyproject.toml',
|
||||
'.python-version or .tool-versions',
|
||||
'Dockerfile',
|
||||
'.mokogitea/workflows/* or .gitea/workflows/* or .gitlab-ci.yml',
|
||||
'.mokogit/workflows/* or .gitea/workflows/* or .gitlab-ci.yml',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -566,8 +566,8 @@ class PythonPlugin extends AbstractProjectPlugin
|
||||
*/
|
||||
private function hasCICD(string $projectPath): bool
|
||||
{
|
||||
return $this->fileExists($projectPath, '.mokogitea/workflows') ||
|
||||
$this->fileExists($projectPath, '.mokogitea/workflows') ||
|
||||
return $this->fileExists($projectPath, '.mokogit/workflows') ||
|
||||
$this->fileExists($projectPath, '.mokogit/workflows') ||
|
||||
$this->fileExists($projectPath, '.gitlab-ci.yml') ||
|
||||
$this->fileExists($projectPath, '.travis.yml') ||
|
||||
$this->fileExists($projectPath, 'tox.ini');
|
||||
|
||||
@@ -126,13 +126,13 @@ class ProjectMetricsCollector
|
||||
|
||||
// CI/CD — check both .github/workflows and .gitea/workflows
|
||||
$hasGithubWf = is_dir("{$path}/.github/workflows");
|
||||
$hasGiteaWf = is_dir("{$path}/.mokogitea/workflows");
|
||||
$this->collectedMetrics['has_ci_workflows'] = ($hasGithubWf || $hasGiteaWf) ? 1 : 0;
|
||||
$hasGitWf = is_dir("{$path}/.mokogit/workflows");
|
||||
$this->collectedMetrics['has_ci_workflows'] = ($hasGithubWf || $hasGitWf) ? 1 : 0;
|
||||
$this->collectedMetrics['workflow_count'] =
|
||||
$this->countFiles("{$path}/.github/workflows", '*.yml') +
|
||||
$this->countFiles("{$path}/.github/workflows", '*.yaml') +
|
||||
$this->countFiles("{$path}/.mokogitea/workflows", '*.yml') +
|
||||
$this->countFiles("{$path}/.mokogitea/workflows", '*.yaml');
|
||||
$this->countFiles("{$path}/.mokogit/workflows", '*.yml') +
|
||||
$this->countFiles("{$path}/.mokogit/workflows", '*.yaml');
|
||||
}
|
||||
|
||||
private function collectNodeJSMetrics(string $path): void
|
||||
|
||||
@@ -206,9 +206,9 @@ class RepositoryHealthChecker
|
||||
|
||||
// Check both .github/workflows and .gitea/workflows
|
||||
$githubDir = "{$path}/.github/workflows";
|
||||
$giteaDir = "{$path}/.mokogitea/workflows";
|
||||
$hasWorkflowDir = is_dir($githubDir) || is_dir($giteaDir);
|
||||
$workflowDir = is_dir($giteaDir) ? $giteaDir : $githubDir;
|
||||
$gitDir = "{$path}/.mokogit/workflows";
|
||||
$hasWorkflowDir = is_dir($githubDir) || is_dir($gitDir);
|
||||
$workflowDir = is_dir($gitDir) ? $gitDir : $githubDir;
|
||||
|
||||
// Check workflows directory exists
|
||||
$this->addCheck(
|
||||
@@ -253,15 +253,15 @@ class RepositoryHealthChecker
|
||||
10
|
||||
);
|
||||
|
||||
// Check for security scanning workflow (CodeQL on GitHub, Trivy on Gitea)
|
||||
// Check for security scanning workflow (CodeQL on GitHub, Trivy on Git)
|
||||
$githubWf = "{$path}/.github/workflows";
|
||||
$giteaWf = "{$path}/.mokogitea/workflows";
|
||||
$gitWf = "{$path}/.mokogit/workflows";
|
||||
$hasSecurityScan = false;
|
||||
if (is_dir($githubWf)) {
|
||||
$hasSecurityScan = !empty(glob("{$githubWf}/*codeql*.yml")) || !empty(glob("{$githubWf}/*codeql*.yaml"));
|
||||
}
|
||||
if (!$hasSecurityScan && is_dir($giteaWf)) {
|
||||
$hasSecurityScan = !empty(glob("{$giteaWf}/*trivy*.yml")) || !empty(glob("{$giteaWf}/*trivy*.yaml"));
|
||||
if (!$hasSecurityScan && is_dir($gitWf)) {
|
||||
$hasSecurityScan = !empty(glob("{$gitWf}/*trivy*.yml")) || !empty(glob("{$gitWf}/*trivy*.yaml"));
|
||||
}
|
||||
$this->addCheck(
|
||||
$category,
|
||||
@@ -270,7 +270,7 @@ class RepositoryHealthChecker
|
||||
10
|
||||
);
|
||||
|
||||
// Check for dependency management (Dependabot on GitHub, Renovate on Gitea)
|
||||
// Check for dependency management (Dependabot on GitHub, Renovate on Git)
|
||||
$this->addCheck(
|
||||
$category,
|
||||
'Dependency management configured',
|
||||
|
||||
@@ -62,7 +62,7 @@ class RepositorySynchronizer
|
||||
?CheckpointManager $checkpoints = null,
|
||||
?GitPlatformAdapter $adapter = null
|
||||
) {
|
||||
$this->adapter = $adapter ?? new MokoGiteaAdapter($apiClient);
|
||||
$this->adapter = $adapter ?? new MokoGitAdapter($apiClient);
|
||||
$this->logger = $logger;
|
||||
$this->metrics = $metrics;
|
||||
$this->checkpoints = $checkpoints ?? new CheckpointManager('.checkpoints');
|
||||
@@ -266,7 +266,7 @@ class RepositorySynchronizer
|
||||
|
||||
/**
|
||||
* Read the platform slug from the remote manifest.xml.
|
||||
* Checks .mokogitea/manifest.xml, then legacy locations (.mokostandards, .github/.mokostandards).
|
||||
* Checks .mokogit/manifest.xml, then legacy locations (.mokostandards, .github/.mokostandards).
|
||||
*
|
||||
* @return string|null Platform slug or null if not found/parseable
|
||||
*/
|
||||
@@ -278,7 +278,7 @@ class RepositorySynchronizer
|
||||
"{$metaDir}/.mokostandards",
|
||||
'.mokostandards',
|
||||
];
|
||||
if ($metaDir === '.mokogitea') {
|
||||
if ($metaDir === '.mokogit') {
|
||||
$paths[] = '.github/.mokostandards';
|
||||
}
|
||||
|
||||
@@ -637,7 +637,7 @@ class RepositorySynchronizer
|
||||
* and convert legacy YAML-like format to the new XML manifest.
|
||||
*
|
||||
* Handles:
|
||||
* 1. Location migration: root or .github/ → .mokogitea/manifest.xml
|
||||
* 1. Location migration: root or .github/ → .mokogit/manifest.xml
|
||||
* 2. Format migration: legacy "platform: xxx" → XML manifest
|
||||
* 3. Update existing XML: refresh <governance><last-synced> timestamp
|
||||
*/
|
||||
@@ -654,7 +654,7 @@ class RepositorySynchronizer
|
||||
|
||||
// ── Collect existing files from all legacy locations ─────────
|
||||
$legacySources = ['.mokostandards'];
|
||||
if ($metaDir === '.mokogitea') {
|
||||
if ($metaDir === '.mokogit') {
|
||||
$legacySources[] = '.github/.mokostandards';
|
||||
}
|
||||
|
||||
@@ -762,7 +762,7 @@ class RepositorySynchronizer
|
||||
* @param string $org Organization name
|
||||
* @param string $repo Repository name
|
||||
* @param string $platform Detected platform slug
|
||||
* @param array $repoInfo Gitea API repo object
|
||||
* @param array $repoInfo Git API repo object
|
||||
* @param string|null $existingContent Current .mokostandards content (XML or legacy)
|
||||
* @return string Well-formed XML content
|
||||
*/
|
||||
@@ -1068,8 +1068,8 @@ class RepositorySynchronizer
|
||||
}
|
||||
|
||||
// Read all .yml files from the template's workflow directory
|
||||
$sourceDir = "{$cacheDir}/.mokogitea/workflows";
|
||||
// Fallback to legacy path if .mokogitea doesn't exist
|
||||
$sourceDir = "{$cacheDir}/.mokogit/workflows";
|
||||
// Fallback to legacy path if .mokogit doesn't exist
|
||||
if (!is_dir($sourceDir)) {
|
||||
$sourceDir = "{$cacheDir}/.gitea/workflows";
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user