Merge dev: wiki updates
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
Deploy MokoGitea / deploy (push) Failing after 28s
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Generic: Repo Health / Report Issues (push) Has been cancelled

This commit is contained in:
Jonathan Miller
2026-06-06 19:50:43 +00:00
7 changed files with 683 additions and 242 deletions
+243 -241
View File
@@ -1,241 +1,243 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.Release
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
# PATH: /templates/workflows/universal/pre-release.yml.template
# VERSION: 05.01.00
# BRIEF: Manual pre-release -- builds dev/alpha/beta/rc packages from any branch
name: "Universal: Pre-Release"
on:
pull_request:
types: [closed]
branches:
- dev
pull_request_target:
types: [synchronize, opened, reopened]
branches:
- main
workflow_dispatch:
inputs:
stability:
description: 'Pre-release channel'
required: true
type: choice
options:
- development
- alpha
- beta
- release-candidate
permissions:
contents: write
env:
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }}
GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }}
jobs:
build:
name: "Build Pre-Release (${{ inputs.stability || 'development' }})"
runs-on: release
if: >-
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' && github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'dev') ||
(github.event_name == 'pull_request_target' && github.event.pull_request.base.ref == 'main')
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.MOKOGITEA_TOKEN }}
ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || '' }}
- name: Setup moko-platform tools
env:
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
run: |
# Use pre-installed /opt/moko-platform if available (updated by cron every 6h)
if [ -f /opt/moko-platform/cli/version_bump.php ] && [ -f /opt/moko-platform/vendor/autoload.php ]; then
echo Using pre-installed /opt/moko-platform
echo MOKO_CLI=/opt/moko-platform/cli >> $GITHUB_ENV
else
echo Falling back to fresh clone
if ! command -v composer &> /dev/null; then
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer >/dev/null 2>&1
fi
rm -rf /tmp/moko-platform-api
git clone --depth 1 --branch main --quiet \
“https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git” \
/tmp/moko-platform-api
cd /tmp/moko-platform-api && composer install --no-dev --no-interaction --quiet
echo “MOKO_CLI=/tmp/moko-platform-api/cli” >> “$GITHUB_ENV”
fi
- name: Detect platform
id: platform
run: |
php ${MOKO_CLI}/manifest_read.php --path . --github-output
- name: Resolve metadata and bump version
id: meta
run: |
# Auto-detect stability: RC for PRs targeting main, else use input or default to development
if [ "${{ github.event_name }}" = "pull_request_target" ] && [ "${{ github.event.pull_request.base.ref }}" = "main" ]; then
STABILITY="release-candidate"
else
STABILITY="${{ inputs.stability || 'development' }}"
fi
case "$STABILITY" in
development) SUFFIX="-dev"; TAG="development" ;;
alpha) SUFFIX="-alpha"; TAG="alpha" ;;
beta) SUFFIX="-beta"; TAG="beta" ;;
release-candidate) SUFFIX="-rc"; TAG="release-candidate" ;;
esac
# Bump version via CLI: patch for dev/alpha/beta, minor for RC
case "$STABILITY" in
release-candidate) BUMP="minor" ;;
*) BUMP="patch" ;;
esac
php ${MOKO_CLI}/version_bump.php --path . $([ "$BUMP" = "minor" ] && echo "--minor") 2>/dev/null || true
# Set stability suffix and verify consistency
VERSION=$(php ${MOKO_CLI}/version_read.php --path . 2>/dev/null || echo "00.00.01")
VERSION=$(echo "$VERSION" | sed 's/-\(dev\|alpha\|beta\|rc\)$//')
php ${MOKO_CLI}/version_set_platform.php \
--path . --version "$VERSION" --branch "${{ github.ref_name }}" --stability "$STABILITY" 2>/dev/null || true
php ${MOKO_CLI}/version_check.php --path . --fix 2>/dev/null || true
# Append suffix for output
if [ -n "$SUFFIX" ]; then
VERSION="${VERSION}${SUFFIX}"
fi
# Commit version bump
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "gitea-actions[bot]"
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_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]"
git push origin HEAD 2>&1
}
# Auto-detect element via manifest_element.php
php ${MOKO_CLI}/manifest_element.php \
--path . --version "$VERSION" --stability "$STABILITY" \
--repo "${GITEA_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 "$ZIP_NAME" ] && ZIP_NAME="${EXT_ELEMENT}-${VERSION}.zip"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "stability=${STABILITY}" >> "$GITHUB_OUTPUT"
echo "suffix=${SUFFIX}" >> "$GITHUB_OUTPUT"
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
echo "zip_name=${ZIP_NAME}" >> "$GITHUB_OUTPUT"
echo "ext_element=${EXT_ELEMENT}" >> "$GITHUB_OUTPUT"
echo "=== Pre-Release: ${EXT_ELEMENT} ${VERSION}${SUFFIX} ==="
- name: Create release
id: release
run: |
TAG="${{ steps.meta.outputs.tag }}"
VERSION="${{ steps.meta.outputs.version }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
php ${MOKO_CLI}/release_create.php \
--path . --version "$VERSION" --tag "$TAG" \
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
--repo "${GITEA_REPO}" --branch dev --prerelease
- name: Update release notes from CHANGELOG.md
run: |
TAG="${{ steps.meta.outputs.tag }}"
VERSION="${{ steps.meta.outputs.version }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
# Extract [Unreleased] section from changelog (everything between [Unreleased] and next ## heading)
if [ -f "CHANGELOG.md" ]; then
NOTES=$(awk '/^## \[Unreleased\]/{found=1; next} /^## \[/{if(found) exit} found{print}' CHANGELOG.md)
[ -z "$NOTES" ] && NOTES="Release ${VERSION}"
else
NOTES="Release ${VERSION}"
fi
# Update release body via API
RELEASE_ID=$(curl -sf -H "Authorization: token ${{ secrets.MOKOGITEA_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
python3 -c "
import json, urllib.request
body = open('/dev/stdin').read()
payload = json.dumps({'body': body}).encode()
req = urllib.request.Request(
'${API_BASE}/releases/${RELEASE_ID}',
data=payload, method='PATCH',
headers={
'Authorization': 'token ${{ secrets.MOKOGITEA_TOKEN }}',
'Content-Type': 'application/json'
})
urllib.request.urlopen(req)
" <<< "$NOTES"
echo "Release notes updated from CHANGELOG.md"
fi
- name: Build package and upload
id: package
run: |
VERSION="${{ steps.meta.outputs.version }}"
TAG="${{ steps.meta.outputs.tag }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_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
# updates.xml is generated dynamically by MokoGitea license server
# No need to build, commit, or sync updates.xml from workflows
- name: "Delete lesser pre-release channels (cascade)"
continue-on-error: true
run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
php ${MOKO_CLI}/release_cascade.php \
--stability "${{ steps.meta.outputs.stability }}" \
--token "${TOKEN}" \
--api-base "${API_BASE}"
- name: Summary
if: always()
run: |
VERSION="${{ steps.meta.outputs.version }}"
STABILITY="${{ steps.meta.outputs.stability }}"
ZIP_NAME="${{ steps.meta.outputs.zip_name }}"
SHA256="${{ steps.package.outputs.sha256_zip }}"
echo "## Pre-Release Complete" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Channel | ${STABILITY} |" >> $GITHUB_STEP_SUMMARY
echo "| Package | \`${ZIP_NAME}\` |" >> $GITHUB_STEP_SUMMARY
echo "| SHA-256 | \`${SHA256:-n/a}\` |" >> $GITHUB_STEP_SUMMARY
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.Release
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
# PATH: /templates/workflows/universal/pre-release.yml.template
# VERSION: 05.01.00
# BRIEF: Manual pre-release -- builds dev/alpha/beta/rc packages from any branch
name: "Universal: Pre-Release"
on:
pull_request:
types: [closed]
branches:
- dev
pull_request_target:
types: [synchronize, opened, reopened]
branches:
- main
workflow_dispatch:
inputs:
stability:
description: 'Pre-release channel'
required: true
type: choice
options:
- development
- alpha
- beta
- release-candidate
permissions:
contents: write
env:
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }}
GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }}
jobs:
build:
name: "Build Pre-Release (${{ inputs.stability || 'development' }})"
runs-on: release
if: >-
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' && github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'dev') ||
(github.event_name == 'pull_request_target' && github.event.pull_request.base.ref == 'main')
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.MOKOGITEA_TOKEN }}
ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || '' }}
- name: Setup moko-platform tools
env:
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
run: |
# Use pre-installed /opt/moko-platform if available (updated by cron every 6h)
if [ -f /opt/moko-platform/cli/version_bump.php ] && [ -f /opt/moko-platform/cli/manifest_element.php ] && [ -f /opt/moko-platform/vendor/autoload.php ]; then
echo Using pre-installed /opt/moko-platform
echo MOKO_CLI=/opt/moko-platform/cli >> $GITHUB_ENV
else
echo Falling back to fresh clone
if ! command -v composer > /dev/null 2>&1; then
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1
fi
rm -rf /tmp/moko-platform-api
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/moko-platform-api
cd /tmp/moko-platform-api && composer install --no-dev --no-interaction --quiet
echo MOKO_CLI=/tmp/moko-platform-api/cli >> $GITHUB_ENV
fi
- name: Detect platform
id: platform
run: |
php ${MOKO_CLI}/manifest_read.php --path . --github-output
- name: Resolve metadata and bump version
id: meta
run: |
# Auto-detect stability: RC for PRs targeting main, else use input or default to development
if [ "${{ github.event_name }}" = "pull_request_target" ] && [ "${{ github.event.pull_request.base.ref }}" = "main" ]; then
STABILITY="release-candidate"
else
STABILITY="${{ inputs.stability || 'development' }}"
fi
case "$STABILITY" in
development) SUFFIX="-dev"; TAG="development" ;;
alpha) SUFFIX="-alpha"; TAG="alpha" ;;
beta) SUFFIX="-beta"; TAG="beta" ;;
release-candidate) SUFFIX="-rc"; TAG="release-candidate" ;;
esac
# Bump version via CLI: patch for dev/alpha/beta, minor for RC
case "$STABILITY" in
release-candidate) BUMP="minor" ;;
*) BUMP="patch" ;;
esac
php ${MOKO_CLI}/version_bump.php --path . $([ "$BUMP" = "minor" ] && echo "--minor") 2>/dev/null || true
# Set stability suffix and verify consistency
VERSION=$(php ${MOKO_CLI}/version_read.php --path . 2>/dev/null || echo "00.00.01")
VERSION=$(echo "$VERSION" | sed 's/-\(dev\|alpha\|beta\|rc\)$//')
php ${MOKO_CLI}/version_set_platform.php \
--path . --version "$VERSION" --branch "${{ github.ref_name }}" --stability "$STABILITY" 2>/dev/null || true
php ${MOKO_CLI}/version_check.php --path . --fix 2>/dev/null || true
# Ensure licensing tags (updateservers, dlid) if enabled in manifest.xml
php ${MOKO_CLI}/manifest_licensing.php --path . --fix 2>/dev/null || true
# Append suffix for output
if [ -n "$SUFFIX" ]; then
VERSION="${VERSION}${SUFFIX}"
fi
# Commit version bump
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "gitea-actions[bot]"
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_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]"
git push origin HEAD 2>&1
}
# Auto-detect element via manifest_element.php
php ${MOKO_CLI}/manifest_element.php \
--path . --version "$VERSION" --stability "$STABILITY" \
--repo "${GITEA_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 "$ZIP_NAME" ] && ZIP_NAME="${EXT_ELEMENT}-${VERSION}.zip"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "stability=${STABILITY}" >> "$GITHUB_OUTPUT"
echo "suffix=${SUFFIX}" >> "$GITHUB_OUTPUT"
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
echo "zip_name=${ZIP_NAME}" >> "$GITHUB_OUTPUT"
echo "ext_element=${EXT_ELEMENT}" >> "$GITHUB_OUTPUT"
echo "=== Pre-Release: ${EXT_ELEMENT} ${VERSION}${SUFFIX} ==="
- name: Create release
id: release
run: |
TAG="${{ steps.meta.outputs.tag }}"
VERSION="${{ steps.meta.outputs.version }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
php ${MOKO_CLI}/release_create.php \
--path . --version "$VERSION" --tag "$TAG" \
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
--repo "${GITEA_REPO}" --branch dev --prerelease
- name: Update release notes from CHANGELOG.md
run: |
TAG="${{ steps.meta.outputs.tag }}"
VERSION="${{ steps.meta.outputs.version }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
# Extract [Unreleased] section from changelog (everything between [Unreleased] and next ## heading)
if [ -f "CHANGELOG.md" ]; then
NOTES=$(awk '/^## \[Unreleased\]/{found=1; next} /^## \[/{if(found) exit} found{print}' CHANGELOG.md)
[ -z "$NOTES" ] && NOTES="Release ${VERSION}"
else
NOTES="Release ${VERSION}"
fi
# Update release body via API
RELEASE_ID=$(curl -sf -H "Authorization: token ${{ secrets.MOKOGITEA_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
python3 -c "
import json, urllib.request
body = open('/dev/stdin').read()
payload = json.dumps({'body': body}).encode()
req = urllib.request.Request(
'${API_BASE}/releases/${RELEASE_ID}',
data=payload, method='PATCH',
headers={
'Authorization': 'token ${{ secrets.MOKOGITEA_TOKEN }}',
'Content-Type': 'application/json'
})
urllib.request.urlopen(req)
" <<< "$NOTES"
echo "Release notes updated from CHANGELOG.md"
fi
- name: Build package and upload
id: package
run: |
VERSION="${{ steps.meta.outputs.version }}"
TAG="${{ steps.meta.outputs.tag }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_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
# updates.xml is generated dynamically by MokoGitea license server
# No need to build, commit, or sync updates.xml from workflows
- name: "Delete lesser pre-release channels (cascade)"
continue-on-error: true
run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
php ${MOKO_CLI}/release_cascade.php \
--stability "${{ steps.meta.outputs.stability }}" \
--token "${TOKEN}" \
--api-base "${API_BASE}"
- name: Summary
if: always()
run: |
VERSION="${{ steps.meta.outputs.version }}"
STABILITY="${{ steps.meta.outputs.stability }}"
ZIP_NAME="${{ steps.meta.outputs.zip_name }}"
SHA256="${{ steps.package.outputs.sha256_zip }}"
echo "## Pre-Release Complete" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Channel | ${STABILITY} |" >> $GITHUB_STEP_SUMMARY
echo "| Package | \`${ZIP_NAME}\` |" >> $GITHUB_STEP_SUMMARY
echo "| SHA-256 | \`${SHA256:-n/a}\` |" >> $GITHUB_STEP_SUMMARY
+32
View File
@@ -0,0 +1,32 @@
# Custom Branding
## Logo & Favicon
Located in the container at `/var/lib/gitea/custom/public/assets/img/`:
- `logo.svg` — Navbar logo
- `logo.png` — Fallback logo
- `favicon.png` — Browser tab icon
- `favicon.svg` — SVG favicon
Source: Moko Consulting CRM favicon
## Landing Page
- `LANDING_PAGE = organizations` in `app.ini`
- Custom JS redirects home/logo clicks to `/explore/organizations`
- After login, users see the organizations list
## Themes
Custom CSS themes at `/var/lib/gitea/custom/public/assets/css/`:
- `theme-moko-dark.css`
- `theme-moko-light.css`
- `theme-moko-auto.css`
---
*Repo: [MokoGitea](https://git.mokoconsulting.tech/MokoConsulting/MokoGitea) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
| Revision | Date | Author | Description |
|---|---|---|---|
| 1.0 | 2026-05-09 | Moko Consulting | Initial version |
+48
View File
@@ -0,0 +1,48 @@
# Deployment
## Docker Image
MokoGitea runs as a custom Docker image built from the `moko/1.25.5-project-api` branch.
### Build
```bash
cd /opt/MokoGitea
git pull
docker build -t mokogitea:1.25.5-project-api -f Dockerfile.rootless .
```
### Deploy
The docker-compose at `/opt/gitea/docker-compose.yml` references the image:
```yaml
services:
gitea:
image: mokogitea:1.25.5-project-api
```
### Update Process
1. Pull latest from `moko/1.25.5-project-api`
2. Rebuild Docker image
3. `docker compose down gitea && docker compose up -d gitea`
## Volumes
| Path | Purpose |
|------|---------|
| `./gitea/data` | Repository data, LFS, avatars |
| `./gitea/conf` | `app.ini` configuration |
## Custom Files
Located at `/var/lib/gitea/custom/`:
- `templates/custom/header.tmpl` — Branding, logo redirect
- `public/assets/img/logo.svg` — Moko logo
- `public/assets/img/favicon.png` — Moko favicon
- `public/assets/css/theme-moko-*.css` — Custom themes
---
*Repo: [MokoGitea](https://git.mokoconsulting.tech/MokoConsulting/MokoGitea) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
| Revision | Date | Author | Description |
|---|---|---|---|
| 1.0 | 2026-05-09 | Moko Consulting | Initial version |
+1 -1
View File
@@ -7,7 +7,7 @@ Moko Consulting's custom fork of [Gitea](https://gitea.com), extending the self-
| **Language** | Go |
| **License** | MIT |
| **Upstream** | Gitea 1.26.1 |
| **Version** | v1.26.1-moko.06.04.00 |
| **Version** | v1.26.1-moko.06.07.03 |
| **Platform** | [Gitea](https://git.mokoconsulting.tech/MokoConsulting/MokoGitea) |
---
+115
View File
@@ -0,0 +1,115 @@
# Org-Level Branch Protection API
## Overview
MokoGitea v1261.0.0 introduces **organization-level branch protection rulesets** that cascade automatically to all repositories within an organization. This eliminates the need to configure identical branch protection rules on each repo individually.
## How Inheritance Works
1. **Repo rules take precedence** — If a repo has its own protection rule for a branch pattern (e.g., `main`), the org rule is ignored for that repo.
2. **Org rules are the fallback** — If no repo-level rule matches a branch, the system checks org-level rules.
3. **Team-based only** — Org rules reference teams, not individual users (use repo-level rules for per-user whitelists).
## API Endpoints
All endpoints require authentication (`token`) and org ownership permissions.
### List Rules
```
GET /api/v1/orgs/{org}/branch_protections
```
### Create Rule
```
POST /api/v1/orgs/{org}/branch_protections
```
**Body:**
```json
{
"rule_name": "main",
"enable_push": true,
"enable_push_whitelist": true,
"push_whitelist_teams": ["developers"],
"enable_merge_whitelist": true,
"merge_whitelist_teams": ["maintainers"],
"required_approvals": 2,
"block_on_rejected_reviews": true,
"block_on_outdated_branch": true,
"dismiss_stale_approvals": true,
"require_signed_commits": false
}
```
### Get Rule
```
GET /api/v1/orgs/{org}/branch_protections/{name}
```
### Update Rule
```
PATCH /api/v1/orgs/{org}/branch_protections/{name}
```
Only fields included in the request body are updated.
### Delete Rule
```
DELETE /api/v1/orgs/{org}/branch_protections/{name}
```
## Glob Patterns
Rule names support glob patterns for matching multiple branches:
| Pattern | Matches |
|---------|---------|
| `main` | Exactly `main` |
| `dev` | Exactly `dev` |
| `rc/*` | `rc/1.0`, `rc/2.0-beta`, etc. |
| `beta/*` | `beta/feature-x`, etc. |
| `release/**` | `release/v1`, `release/v1/hotfix`, etc. |
## Example: Protect All Standard Branches
```bash
TOKEN="your-token"
ORG="MokoConsulting"
API="https://git.mokoconsulting.tech/api/v1"
for BRANCH in main dev "rc/*" "beta/*" "alpha/*"; do
curl -X POST "$API/orgs/$ORG/branch_protections" \
-H "Authorization: token $TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"rule_name\": \"$BRANCH\",
\"enable_push\": true,
\"enable_push_whitelist\": true,
\"push_whitelist_teams\": [\"developers\"],
\"required_approvals\": 1,
\"block_on_rejected_reviews\": true,
\"block_on_outdated_branch\": true
}"
done
```
## Configuration: Help & Support URLs
Also new in v1261.0.0 — configurable help/support links in `app.ini`:
```ini
[DEFAULT]
HELP_URL = https://docs.mokoconsulting.tech
SUPPORT_URL = https://mokoconsulting.tech/support
```
These replace the hardcoded `docs.gitea.com` links in the navigation bar and are visible in **Site Admin > Configuration**.
## Version Convention
MokoGitea uses `1261.xx.xx` versioning where `1261` represents the fork starting point from upstream Gitea. Minor and patch numbers track MokoGitea-specific releases.
+202
View File
@@ -0,0 +1,202 @@
# Project Board API Reference
Complete REST API for managing Gitea project boards, columns, and issue cards. This API was added by MokoGitea and is not available in upstream Gitea.
## Authentication
All write endpoints require a token with `issue` scope:
```
Authorization: token YOUR_TOKEN
```
## Projects
### List Projects
```
GET /api/v1/repos/{owner}/{repo}/projects
```
Query parameters:
- `state``open` (default), `closed`, or `all`
- `page` — page number (1-based)
- `limit` — results per page
Response: Array of Project objects
### Create Project
```
POST /api/v1/repos/{owner}/{repo}/projects
```
Body:
```json
{
"title": "Sprint Q2 2026",
"description": "Second quarter sprint",
"board_type": 1,
"card_type": 0
}
```
- `board_type`: 0=none, 1=basic kanban, 2=bug triage
- `card_type`: 0=text only, 1=images and text
### Get Project
```
GET /api/v1/repos/{owner}/{repo}/projects/{id}
```
### Update Project
```
PATCH /api/v1/repos/{owner}/{repo}/projects/{id}
```
Body:
```json
{
"title": "Updated Title",
"description": "Updated description"
}
```
### Delete Project
```
DELETE /api/v1/repos/{owner}/{repo}/projects/{id}
```
### Close/Reopen Project
```
POST /api/v1/repos/{owner}/{repo}/projects/{id}/close
POST /api/v1/repos/{owner}/{repo}/projects/{id}/reopen
```
## Columns
### List Columns
```
GET /api/v1/repos/{owner}/{repo}/projects/{id}/columns
```
### Create Column
```
POST /api/v1/repos/{owner}/{repo}/projects/{id}/columns
```
Body:
```json
{
"title": "Backlog",
"color": "#0075ca"
}
```
### Delete Column
```
DELETE /api/v1/repos/{owner}/{repo}/projects/{id}/columns/{columnId}
```
## Issue Cards
### List Issues in Column
```
GET /api/v1/repos/{owner}/{repo}/projects/{id}/columns/{columnId}/issues
```
Response: Array of ProjectColumnIssue objects with `issue_id`, `project_id`, `column_id`, `sorting`
### Add Issue to Column
```
POST /api/v1/repos/{owner}/{repo}/projects/{id}/columns/{columnId}/issues
```
Body:
```json
{
"issue_id": 42
}
```
### Move Issue Between Columns
```
PATCH /api/v1/repos/{owner}/{repo}/projects/{id}/issues/{issueId}/move
```
Body:
```json
{
"column_id": 5,
"sorting": 0
}
```
### Remove Issue from Project
```
DELETE /api/v1/repos/{owner}/{repo}/projects/{id}/issues/{issueId}
```
## Data Types
### Project
```json
{
"id": 1,
"title": "Roadmap",
"description": "Development roadmap",
"owner_id": 2,
"repo_id": 68,
"creator_id": 1,
"is_closed": false,
"created_at": "2026-05-08T00:06:45Z",
"updated_at": "2026-05-08T00:06:45Z",
"closed_at": null
}
```
### ProjectColumn
```json
{
"id": 7,
"title": "Backlog",
"sorting": 0,
"color": "#0075ca",
"project_id": 1,
"default": false,
"created_at": "2026-05-08T00:06:58Z",
"updated_at": "2026-05-08T00:06:58Z"
}
```
### ProjectColumnIssue
```json
{
"id": 1,
"issue_id": 42,
"project_id": 1,
"column_id": 7,
"sorting": 0
}
```
## MCP Integration
The `project-mcp` server wraps this API. Key tool: `project_setup_roadmap` creates a full project board with columns and loads all open issues in one call.
## Quick Start
```bash
# Create a project
curl -X POST -H "Authorization: token TOKEN" \
https://git.mokoconsulting.tech/api/v1/repos/MokoConsulting/MokoCRM/projects \
-d '{"title":"Roadmap","board_type":1}'
# Add columns
curl -X POST -H "Authorization: token TOKEN" \
https://git.mokoconsulting.tech/api/v1/repos/MokoConsulting/MokoCRM/projects/1/columns \
-d '{"title":"Backlog"}'
# Add an issue
curl -X POST -H "Authorization: token TOKEN" \
https://git.mokoconsulting.tech/api/v1/repos/MokoConsulting/MokoCRM/projects/1/columns/1/issues \
-d '{"issue_id":42}'
```
---
*Repo: [MokoGitea](https://git.mokoconsulting.tech/MokoConsulting/MokoGitea) · [moko-platform](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
| Revision | Date | Author | Description |
|---|---|---|---|
| 1.0 | 2026-05-09 | Moko Consulting | Initial version |
+42
View File
@@ -0,0 +1,42 @@
# MokoGitea Roadmap
## Recently Completed (v1.26.1-moko.06.07)
- Well-known file tabs (README/LICENSE/CONTRIBUTING/SECURITY/CHANGELOG)
- Custom issue statuses with auto close/reopen
- Org-level issue priorities (Critical/High/Medium/Low)
- Repo manifest settings with REST API
- Manifest auto-sync on push to default branch
- Status dropdown replaces close button
- Auto-seed default statuses and priorities for orgs
- MCP server published to npm (@mokoconsulting/mokogitea-mcp)
- MCP SSE transport for hosted deployments
## In Progress
- Granular role-based permissions for all features (#9)
- Built-in secret scanning (#508)
- Enterprise Wiki with hierarchical folder navigation (#79)
- Wire moko-platform CLI to manifest API (#505)
## Planned
- Standard status presets and cross-org migration (#507)
- Auto-create default teams on org creation (#513)
- Update server reads from repo_manifest (#512)
- Payment gateways for license keys (#135)
- Independent visibility controls for issues/wiki/projects (#133)
## Infrastructure
- MCP SSE endpoint at git.mokoconsulting.tech/mcp
- Smithery/Claude Code marketplace listing
- Docker image for MCP server
- npm auto-publish workflow on release
---
| Revision | Date | Author | Description |
|---|---|---|---|
| 2.0 | 2026-06-06 | Jonathan Miller (@jmiller) | Complete rewrite with current features and priorities |
| 1.0 | 2026-05-09 | Jonathan Miller (@jmiller) | Initial version |