Compare commits

..

1 Commits

Author SHA1 Message Date
Jonathan Miller add7c0da4d feat: make metadata/manifest GET endpoint publicly accessible (#676)
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Has been skipped
Universal: Auto Version Bump / Version Bump (push) Successful in 11s
PR RC Release / Build RC Release (pull_request) Failing after 54s
Universal: PR Check / Secret Scan (pull_request) Successful in 54s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 42s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Publish to Composer / Publish Package (release) Failing after 5s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
Remove reqRepoReader auth requirement from GET /repos/{owner}/{repo}/metadata
and /manifest endpoints. PUT (update) still requires token + admin.
2026-06-21 10:18:07 -05:00
2541 changed files with 16152 additions and 33632 deletions
View File
-10
View File
@@ -115,18 +115,8 @@ prime/
/.github/copilot-instructions.md
/llms.txt
# Real deploy env files -- NEVER commit secrets. Keep the *.env.example templates.
.env
*.env
!*.env.example
!.env.example
deploy/**/.env
# Ignore worktrees when working on multiple branches
.worktrees/
# A Makefile for custom make targets
Makefile.local
# Local clone of the MCP server (separate repo, not a submodule of this project)
/mcp-mokogit-api/
+4 -4
View File
@@ -44,7 +44,7 @@ linters:
desc: use os or io instead
- pkg: golang.org/x/exp
desc: it's experimental and unreliable
- pkg: code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/git/internal
- pkg: code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/git/internal
desc: do not use the internal package, use AddXxx function instead
- pkg: gopkg.in/ini.v1
desc: do not use the ini package, use gitea's config system instead
@@ -56,9 +56,9 @@ linters:
files:
- '**/models/migrations/**/*.go'
deny:
- pkg: code.mokoconsulting.tech/MokoConsulting/MokoGIT/models$
- pkg: code.mokoconsulting.tech/MokoConsulting/MokoGitea/models$
desc: migrations must not depend on the models package
- pkg: code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/structs
- pkg: code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/structs
desc: migrations must not depend on modules/structs (API structures change over time)
nolintlint:
allow-unused: false
@@ -179,7 +179,7 @@ formatters:
custom-order: true
sections:
- standard
- prefix(code.mokoconsulting.tech/MokoConsulting/MokoGIT)
- prefix(code.mokoconsulting.tech/MokoConsulting/MokoGitea)
- blank
- default
gofumpt:
@@ -1,9 +0,0 @@
---
name: ".mokogit Test Template"
about: "Verify .mokogit issue templates work"
labels: ["test"]
---
This template was loaded from `.mokogit/ISSUE_TEMPLATE/`.
If you can see this, the `.mokogit` dot-folder feature is working.
-68
View File
@@ -1,68 +0,0 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGIT.Workflow
# INGROUP: mokocli.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
# PATH: /.mokogit/workflows/ci-issue-reporter.yml
# VERSION: 01.00.00
# 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"
on:
workflow_call:
inputs:
gate:
description: "CI gate name (e.g. PR Validation, Repository Health)"
required: true
type: string
details:
description: "Human-readable failure description"
required: true
type: string
severity:
description: "error or warning"
required: false
type: string
default: "error"
workflow:
description: "Workflow name for the issue title"
required: false
type: string
default: ""
secrets:
MOKOGIT_TOKEN:
required: true
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
report:
name: "Report: ${{ inputs.gate }}"
runs-on: ubuntu-latest
steps:
- name: Clone MokoCLI
env:
MOKOGIT_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
run: |
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:
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 \
--gate "${{ inputs.gate }}" \
--details "${{ inputs.details }}" \
--severity "${{ inputs.severity }}" \
--workflow "${{ inputs.workflow }}"
-136
View File
@@ -1,136 +0,0 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
# BRIEF: Build and deploy to the Dev environment on push to the dev branch.
# Portable across Go server repos: ALL deployment config comes from repo
# Actions variables (vars.*) and secrets (secrets.*), nothing hardcoded.
# The dev branch is the ongoing integration branch.
# OWNER: Template-Go (canonical source; syncs to the root workflows dir). See Template-Go#3.
#
# Required repo VARIABLES (all tier-scoped so each environment is independent —
# a repo may host its rc/dev/prod tiers on different machines):
# DEV_SSH_HOST, DEV_SSH_PORT, DEV_SSH_USERNAME - SSH deploy target for the dev tier
# DEV_REGISTRY, DEV_REGISTRY_USER, DEV_IMAGE - container registry + login user + image
# DEV_CONTAINER - compose service/container to recreate
# DEV_COMPOSE_PROJECT - docker compose -p project name
# DEV_COMPOSE_DIR - dir containing docker-compose.yml on host
# DEV_SOURCE_DIR - build source checkout on host
# DEV_TAG_ENV - compose env-var name that pins the image tag
# DEV_HEALTH_URL - external URL to verify after deploy
# Required SECRETS (already configured org-wide; reused, not re-set):
# DEPLOY_SSH_KEY - deploy private key (repo/org secret)
# MOKOGIT_TOKEN - registry/API token (org secret)
name: Deploy (Dev)
on:
push:
branches:
- dev
# Manual trigger for isolated end-to-end tests.
# Runs on the ref it is dispatched from.
workflow_dispatch:
concurrency:
group: deploy-dev
cancel-in-progress: true
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
deploy-dev:
name: "Build & Deploy to Dev"
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Determine version
id: config
run: |
VERSION=$(git describe --tags --always 2>/dev/null || echo "dev-$(git rev-parse --short HEAD)")
echo "tag=${VERSION}-dev" >> $GITHUB_OUTPUT
echo "Version: ${VERSION}-dev"
- name: Write deploy key
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
run: |
mkdir -p ~/.ssh
echo "$DEPLOY_KEY" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
- name: Build and deploy to RC via SSH
env:
REGISTRY_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
TAG: ${{ steps.config.outputs.tag }}
run: |
# Runner-side values (TAG, REGISTRY_TOKEN) are injected into the remote shell
# via an env prefix; a *quoted* heredoc keeps every $var expanding once, on the
# remote. Repo variables (vars.*) are substituted inline by Actions before ssh.
ssh -i ~/.ssh/deploy_key -p ${{ vars.DEV_SSH_PORT }} \
-o ConnectTimeout=30 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
-o ServerAliveInterval=30 -o ServerAliveCountMax=10 \
${{ vars.DEV_SSH_USERNAME }}@${{ vars.DEV_SSH_HOST }} \
"TAG='$TAG' REGISTRY_TOKEN='$REGISTRY_TOKEN' bash -s" <<'DEPLOY_EOF'
set -e
echo 'SSH connected to Dev environment'
if [ -z "$TAG" ]; then
echo 'ERROR: TAG is empty; refusing to build an untagged image' >&2
exit 1
fi
HEALTH_FMT='{{.State.Health.Status}}'
echo 'Cleaning Docker build cache...'
docker builder prune -af 2>/dev/null || true
docker image prune -af 2>/dev/null || true
echo 'Pulling source...'
SOURCE_DIR='${{ vars.DEV_SOURCE_DIR }}'
if [ ! -d "$SOURCE_DIR/.git" ]; then
git clone -b dev https://x-access-token:${REGISTRY_TOKEN}@git.mokoconsulting.tech/${{ github.repository }}.git "$SOURCE_DIR"
fi
cd "$SOURCE_DIR"
git remote set-url origin https://x-access-token:${REGISTRY_TOKEN}@git.mokoconsulting.tech/${{ github.repository }}.git 2>/dev/null || true
git fetch origin dev
git reset --hard origin/dev
echo "Building image: ${{ vars.DEV_REGISTRY }}/${{ vars.DEV_IMAGE }}:$TAG"
docker build --no-cache --build-arg GOFLAGS='-p 1' \
--tag "${{ vars.DEV_REGISTRY }}/${{ vars.DEV_IMAGE }}:$TAG" \
-f Dockerfile .
echo 'Pushing to registry...'
echo "$REGISTRY_TOKEN" | docker login ${{ vars.DEV_REGISTRY }} -u ${{ vars.DEV_REGISTRY_USER }} --password-stdin
docker push "${{ vars.DEV_REGISTRY }}/${{ vars.DEV_IMAGE }}:$TAG"
echo 'Restarting Dev container...'
cd '${{ vars.DEV_COMPOSE_DIR }}'
# Drive the rc service image tag via its compose env-var (no sed on the shared
# file); remove any lingering fixed-name container first, then force-recreate.
docker rm -f '${{ vars.DEV_CONTAINER }}' 2>/dev/null || true
${{ vars.DEV_TAG_ENV }}="$TAG" docker compose -p '${{ vars.DEV_COMPOSE_PROJECT }}' up -d --force-recreate '${{ vars.DEV_CONTAINER }}'
echo 'Health check...'
for i in 1 2 3 4 5 6 7 8; do
sleep 15
if docker inspect --format="$HEALTH_FMT" '${{ vars.DEV_CONTAINER }}' 2>/dev/null | grep -q healthy; then
echo 'Dev container healthy!'
exit 0
fi
echo "Waiting... (attempt $i/8)"
done
echo 'Health check failed'
docker logs '${{ vars.DEV_CONTAINER }}' --tail 20
exit 1
DEPLOY_EOF
- name: Verify Dev instance
continue-on-error: true
run: |
sleep 5
ssh -i ~/.ssh/deploy_key -p ${{ vars.DEV_SSH_PORT }} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${{ vars.DEV_SSH_USERNAME }}@${{ vars.DEV_SSH_HOST }} "curl -sf '${{ vars.DEV_HEALTH_URL }}'" && echo " Dev API healthy"
-136
View File
@@ -1,136 +0,0 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
# BRIEF: Build and deploy to the Prod environment on push to the main branch.
# Portable across Go server repos: ALL deployment config comes from repo
# Actions variables (vars.*) and secrets (secrets.*), nothing hardcoded.
# Prod deploys on merge to main (dev -> rc -> main pipeline).
# OWNER: Template-Go (canonical source; syncs to the root workflows dir). See Template-Go#3.
#
# Required repo VARIABLES (all tier-scoped so each environment is independent —
# a repo may host its rc/dev/prod tiers on different machines):
# PROD_SSH_HOST, PROD_SSH_PORT, PROD_SSH_USERNAME - SSH deploy target for the prod tier
# PROD_REGISTRY, PROD_REGISTRY_USER, PROD_IMAGE - container registry + login user + image
# PROD_CONTAINER - compose service/container to recreate
# PROD_COMPOSE_PROJECT - docker compose -p project name
# PROD_COMPOSE_DIR - dir containing docker-compose.yml on host
# PROD_SOURCE_DIR - build source checkout on host
# PROD_TAG_ENV - compose env-var name that pins the image tag
# PROD_HEALTH_URL - external URL to verify after deploy
# Required SECRETS (already configured org-wide; reused, not re-set):
# DEPLOY_SSH_KEY - deploy private key (repo/org secret)
# MOKOGIT_TOKEN - registry/API token (org secret)
name: Deploy (Prod)
on:
push:
branches:
- main
# Manual trigger for a prod re-deploy.
# Runs on the ref it is dispatched from (use main).
workflow_dispatch:
concurrency:
group: deploy-prod
cancel-in-progress: false
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
deploy-prod:
name: "Build & Deploy to Prod"
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Determine version
id: config
run: |
VERSION=$(git describe --tags --always 2>/dev/null || echo "$(git rev-parse --short HEAD)")
echo "tag=${VERSION}" >> $GITHUB_OUTPUT
echo "Version: ${VERSION}"
- name: Write deploy key
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
run: |
mkdir -p ~/.ssh
echo "$DEPLOY_KEY" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
- name: Build and deploy to RC via SSH
env:
REGISTRY_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
TAG: ${{ steps.config.outputs.tag }}
run: |
# Runner-side values (TAG, REGISTRY_TOKEN) are injected into the remote shell
# via an env prefix; a *quoted* heredoc keeps every $var expanding once, on the
# remote. Repo variables (vars.*) are substituted inline by Actions before ssh.
ssh -i ~/.ssh/deploy_key -p ${{ vars.PROD_SSH_PORT }} \
-o ConnectTimeout=30 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
-o ServerAliveInterval=30 -o ServerAliveCountMax=10 \
${{ vars.PROD_SSH_USERNAME }}@${{ vars.PROD_SSH_HOST }} \
"TAG='$TAG' REGISTRY_TOKEN='$REGISTRY_TOKEN' bash -s" <<'DEPLOY_EOF'
set -e
echo 'SSH connected to Prod environment'
if [ -z "$TAG" ]; then
echo 'ERROR: TAG is empty; refusing to build an untagged image' >&2
exit 1
fi
HEALTH_FMT='{{.State.Health.Status}}'
echo 'Cleaning Docker build cache...'
docker builder prune -af 2>/dev/null || true
docker image prune -af 2>/dev/null || true
echo 'Pulling source...'
SOURCE_DIR='${{ vars.PROD_SOURCE_DIR }}'
if [ ! -d "$SOURCE_DIR/.git" ]; then
git clone -b main https://x-access-token:${REGISTRY_TOKEN}@git.mokoconsulting.tech/${{ github.repository }}.git "$SOURCE_DIR"
fi
cd "$SOURCE_DIR"
git remote set-url origin https://x-access-token:${REGISTRY_TOKEN}@git.mokoconsulting.tech/${{ github.repository }}.git 2>/dev/null || true
git fetch origin main
git reset --hard origin/main
echo "Building image: ${{ vars.PROD_REGISTRY }}/${{ vars.PROD_IMAGE }}:$TAG"
docker build --no-cache --build-arg GOFLAGS='-p 1' \
--tag "${{ vars.PROD_REGISTRY }}/${{ vars.PROD_IMAGE }}:$TAG" \
-f Dockerfile .
echo 'Pushing to registry...'
echo "$REGISTRY_TOKEN" | docker login ${{ vars.PROD_REGISTRY }} -u ${{ vars.PROD_REGISTRY_USER }} --password-stdin
docker push "${{ vars.PROD_REGISTRY }}/${{ vars.PROD_IMAGE }}:$TAG"
echo 'Restarting Prod container...'
cd '${{ vars.PROD_COMPOSE_DIR }}'
# Drive the rc service image tag via its compose env-var (no sed on the shared
# file); remove any lingering fixed-name container first, then force-recreate.
docker rm -f '${{ vars.PROD_CONTAINER }}' 2>/dev/null || true
${{ vars.PROD_TAG_ENV }}="$TAG" docker compose -p '${{ vars.PROD_COMPOSE_PROJECT }}' up -d --force-recreate '${{ vars.PROD_CONTAINER }}'
echo 'Health check...'
for i in 1 2 3 4 5 6 7 8; do
sleep 15
if docker inspect --format="$HEALTH_FMT" '${{ vars.PROD_CONTAINER }}' 2>/dev/null | grep -q healthy; then
echo 'Prod container healthy!'
exit 0
fi
echo "Waiting... (attempt $i/8)"
done
echo 'Health check failed'
docker logs '${{ vars.PROD_CONTAINER }}' --tail 20
exit 1
DEPLOY_EOF
- name: Verify Prod instance
continue-on-error: true
run: |
sleep 5
ssh -i ~/.ssh/deploy_key -p ${{ vars.PROD_SSH_PORT }} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${{ vars.PROD_SSH_USERNAME }}@${{ vars.PROD_SSH_HOST }} "curl -sf '${{ vars.PROD_HEALTH_URL }}'" && echo " Prod API healthy"
-138
View File
@@ -1,138 +0,0 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
# BRIEF: Build and deploy to the RC environment on push to the rc branch.
# Portable across Go server repos: ALL deployment config comes from repo
# Actions variables (vars.*) and secrets (secrets.*), nothing hardcoded.
# The rc branch is created by promote-rc when a PR to main opens.
# OWNER: Template-Go (canonical source; syncs to the root workflows dir). See Template-Go#3.
#
# Required repo VARIABLES (all tier-scoped so each environment is independent —
# a repo may host its rc/dev/prod tiers on different machines):
# RC_SSH_HOST, RC_SSH_PORT, RC_SSH_USERNAME - SSH deploy target for the rc tier
# RC_REGISTRY, RC_REGISTRY_USER, RC_IMAGE - container registry + login user + image
# RC_CONTAINER - compose service/container to recreate
# RC_COMPOSE_PROJECT - docker compose -p project name
# RC_COMPOSE_DIR - dir containing docker-compose.yml on host
# RC_SOURCE_DIR - build source checkout on host
# RC_TAG_ENV - compose env-var name that pins the image tag
# RC_HEALTH_URL - external URL to verify after deploy
# Required SECRETS (already configured org-wide; reused, not re-set):
# DEPLOY_SSH_KEY - deploy private key (repo/org secret)
# MOKOGIT_TOKEN - registry/API token (org secret)
name: Deploy (RC)
on:
push:
branches:
- rc
# Manual trigger for isolated end-to-end tests without a full RC promotion.
# Runs on the ref it is dispatched from; that ref must carry current source
# (>= the RC database migration version) or the rebuilt image will refuse the
# newer DB. Dispatch from `rc` once `rc` is current.
workflow_dispatch:
concurrency:
group: deploy-rc
cancel-in-progress: true
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
deploy-rc:
name: "Build & Deploy to RC"
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Determine version
id: config
run: |
VERSION=$(git describe --tags --always 2>/dev/null || echo "rc-$(git rev-parse --short HEAD)")
echo "tag=${VERSION}-rc" >> $GITHUB_OUTPUT
echo "Version: ${VERSION}-rc"
- name: Write deploy key
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
run: |
mkdir -p ~/.ssh
echo "$DEPLOY_KEY" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
- name: Build and deploy to RC via SSH
env:
REGISTRY_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
TAG: ${{ steps.config.outputs.tag }}
run: |
# Runner-side values (TAG, REGISTRY_TOKEN) are injected into the remote shell
# via an env prefix; a *quoted* heredoc keeps every $var expanding once, on the
# remote. Repo variables (vars.*) are substituted inline by Actions before ssh.
ssh -i ~/.ssh/deploy_key -p ${{ vars.RC_SSH_PORT }} \
-o ConnectTimeout=30 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
-o ServerAliveInterval=30 -o ServerAliveCountMax=10 \
${{ vars.RC_SSH_USERNAME }}@${{ vars.RC_SSH_HOST }} \
"TAG='$TAG' REGISTRY_TOKEN='$REGISTRY_TOKEN' bash -s" <<'DEPLOY_EOF'
set -e
echo 'SSH connected to RC environment'
if [ -z "$TAG" ]; then
echo 'ERROR: TAG is empty; refusing to build an untagged image' >&2
exit 1
fi
HEALTH_FMT='{{.State.Health.Status}}'
echo 'Cleaning Docker build cache...'
docker builder prune -af 2>/dev/null || true
docker image prune -af 2>/dev/null || true
echo 'Pulling source...'
SOURCE_DIR='${{ vars.RC_SOURCE_DIR }}'
if [ ! -d "$SOURCE_DIR/.git" ]; then
git clone -b rc https://x-access-token:${REGISTRY_TOKEN}@git.mokoconsulting.tech/${{ github.repository }}.git "$SOURCE_DIR"
fi
cd "$SOURCE_DIR"
git remote set-url origin https://x-access-token:${REGISTRY_TOKEN}@git.mokoconsulting.tech/${{ github.repository }}.git 2>/dev/null || true
git fetch origin rc
git reset --hard origin/rc
echo "Building image: ${{ vars.RC_REGISTRY }}/${{ vars.RC_IMAGE }}:$TAG"
docker build --no-cache --build-arg GOFLAGS='-p 1' \
--tag "${{ vars.RC_REGISTRY }}/${{ vars.RC_IMAGE }}:$TAG" \
-f Dockerfile .
echo 'Pushing to registry...'
echo "$REGISTRY_TOKEN" | docker login ${{ vars.RC_REGISTRY }} -u ${{ vars.RC_REGISTRY_USER }} --password-stdin
docker push "${{ vars.RC_REGISTRY }}/${{ vars.RC_IMAGE }}:$TAG"
echo 'Restarting RC container...'
cd '${{ vars.RC_COMPOSE_DIR }}'
# Drive the rc service image tag via its compose env-var (no sed on the shared
# file); remove any lingering fixed-name container first, then force-recreate.
docker rm -f '${{ vars.RC_CONTAINER }}' 2>/dev/null || true
${{ vars.RC_TAG_ENV }}="$TAG" docker compose -p '${{ vars.RC_COMPOSE_PROJECT }}' up -d --force-recreate '${{ vars.RC_CONTAINER }}'
echo 'Health check...'
for i in 1 2 3 4 5 6 7 8; do
sleep 15
if docker inspect --format="$HEALTH_FMT" '${{ vars.RC_CONTAINER }}' 2>/dev/null | grep -q healthy; then
echo 'RC container healthy!'
exit 0
fi
echo "Waiting... (attempt $i/8)"
done
echo 'Health check failed'
docker logs '${{ vars.RC_CONTAINER }}' --tail 20
exit 1
DEPLOY_EOF
- name: Verify RC instance
continue-on-error: true
run: |
sleep 5
ssh -i ~/.ssh/deploy_key -p ${{ vars.RC_SSH_PORT }} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${{ vars.RC_SSH_USERNAME }}@${{ vars.RC_SSH_HOST }} "curl -sf '${{ vars.RC_HEALTH_URL }}'" && echo " RC API healthy"
File diff suppressed because it is too large Load Diff
-130
View File
@@ -1,130 +0,0 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGIT.Workflow.Template
# INGROUP: MokoStandards.CI
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Joomla
# PATH: /.mokogit/workflows/version-set.yml
# VERSION: 01.00.00
# BRIEF: Set or reset the extension version across all version-bearing files
name: "Joomla: Set Version"
on:
workflow_dispatch:
inputs:
version:
description: "Version number (e.g. 01.00.00)"
required: true
type: string
branch:
description: "Branch to update (default: current)"
required: false
type: string
permissions:
contents: write
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
set-version:
name: Set Version to ${{ inputs.version }}
runs-on: ubuntu-latest
steps:
- name: Validate version format
run: |
VERSION="${{ inputs.version }}"
if ! echo "$VERSION" | grep -qP '^\d{2}\.\d{2}\.\d{2}$'; then
echo "::error::Invalid version format '${VERSION}' — expected XX.YY.ZZ (e.g. 01.00.00)"
exit 1
fi
echo "VERSION=${VERSION}" >> "$GITHUB_ENV"
- name: Checkout
uses: actions/checkout@v4
with:
token: ${{ secrets.MOKOGIT_TOKEN || github.token }}
ref: ${{ inputs.branch || github.ref }}
fetch-depth: 1
- name: Update manifest version
run: |
MANIFEST=""
for XML_FILE in $(find . -maxdepth 3 -name "*.xml" -not -path "./.git/*" -not -path "./vendor/*"); do
if grep -q "<extension" "$XML_FILE" 2>/dev/null; then
MANIFEST="$XML_FILE"
break
fi
done
if [ -z "$MANIFEST" ]; then
echo "::warning::No Joomla extension manifest found — skipping manifest update"
else
OLD_VER=$(grep -oP '<version>\K[^<]+' "$MANIFEST" | head -1)
sed -i "s|<version>${OLD_VER}</version>|<version>${VERSION}</version>|" "$MANIFEST"
echo "Manifest: ${OLD_VER} → ${VERSION} (${MANIFEST})"
fi
- name: Update README.md version
run: |
if [ -f "README.md" ]; then
if grep -qP '^\s*VERSION:\s*\d' README.md; then
sed -i -E "s/(VERSION:\s*)[0-9]{2}\.[0-9]{2}\.[0-9]{2}/\1${VERSION}/" README.md
echo "README.md version updated to ${VERSION}"
else
echo "::warning::No VERSION line found in README.md — skipping"
fi
fi
- name: Update CHANGELOG.md
run: |
if [ -f "CHANGELOG.md" ]; then
DATE=$(date +%Y-%m-%d)
# Check if this version already has an entry
if grep -q "^\#\# \[${VERSION}\]" CHANGELOG.md; then
echo "CHANGELOG.md already has entry for ${VERSION} — skipping"
else
# Insert new version entry after [Unreleased] or at the top after header
if grep -q '^\#\# \[Unreleased\]' CHANGELOG.md; then
sed -i "/^\#\# \[Unreleased\]/a\\\\n## [${VERSION}] --- ${DATE}" CHANGELOG.md
else
sed -i "/^\# Changelog/a\\\\n## [Unreleased]\n\n## [${VERSION}] --- ${DATE}" CHANGELOG.md
fi
echo "CHANGELOG.md: added entry for ${VERSION}"
fi
else
echo "::warning::No CHANGELOG.md found — skipping"
fi
- name: Update FILE INFORMATION blocks
run: |
# Update VERSION in file header blocks (# VERSION: XX.YY.ZZ)
find . -maxdepth 1 -type f \( -name "*.yml" -o -name "*.yaml" -o -name "*.php" -o -name "*.md" \) \
-not -path "./.git/*" -not -path "./vendor/*" -print0 2>/dev/null | \
while IFS= read -r -d '' FILE; do
if head -20 "$FILE" | grep -qP '^\s*#?\s*VERSION:\s*\d{2}\.\d{2}\.\d{2}'; then
sed -i -E "s/(#?\s*VERSION:\s*)[0-9]{2}\.[0-9]{2}\.[0-9]{2}/\1${VERSION}/" "$FILE"
echo "Updated FILE INFORMATION VERSION in ${FILE}"
fi
done
- name: Commit and push
run: |
git config user.name "Moko Consulting [bot]"
git config user.email "hello@mokoconsulting.tech"
git add -A
if git diff --cached --quiet; then
echo "No version changes detected — nothing to commit"
else
git commit -m "chore: set version to ${VERSION} [skip bump]
Authored-by: Moko Consulting"
git push
echo "### Version Set" >> $GITHUB_STEP_SUMMARY
echo "Version updated to \`${VERSION}\` on branch \`${GITHUB_REF_NAME}\`" >> $GITHUB_STEP_SUMMARY
fi
+4 -4
View File
@@ -1,4 +1,4 @@
# MokoGIT
# MokoGitea
Fork of Gitea -- self-hosted Git service at git.mokoconsulting.tech. Go backend + TypeScript frontend.
@@ -7,9 +7,9 @@ Fork of Gitea -- self-hosted Git service at git.mokoconsulting.tech. Go backend
| Field | Value |
|---|---|
| **Language** | Go 1.26+ / TypeScript |
| **Module** | `code.mokoconsulting.tech/MokoConsulting/MokoGIT` |
| **Module** | `code.mokoconsulting.tech/MokoConsulting/MokoGitea` |
| **Branch** | develop on `dev`, merge to `main` (protected) |
| **Wiki** | [MokoGIT Wiki](https://git.mokoconsulting.tech/MokoConsulting/MokoGIT/wiki) |
| **Wiki** | [MokoGitea Wiki](https://git.mokoconsulting.tech/MokoConsulting/MokoGitea/wiki) |
## Commands
@@ -37,6 +37,6 @@ GITEA_TEST_E2E_FLAGS='<filepath>' make test-e2e # Single Playwright test
- TypeScript: use `!` (non-null assertion) not `?.`/`??` when value is known to exist
- CSS: prefer `flex-*` helpers over per-child `tw-ml-*`/`tw-mr-*` margins
- Add `Co-Authored-By` lines to all commits
- **Workflow directory**: `.mokogit/` (not `.gitea/` or `.github/`)
- **Workflow directory**: `.mokogitea/` (not `.gitea/` or `.github/`)
- **Attribution**: `Authored-by: Moko Consulting`
- **Standards**: [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home)
@@ -1,7 +1,7 @@
---
name: Feature Request
about: Suggest a new feature or enhancement
title: '(feat) '
title: '[FEATURE] '
labels: 'enhancement'
assignees: ''
@@ -0,0 +1,9 @@
---
name: ".mokogitea Test Template"
about: "Verify .mokogitea issue templates work"
labels: ["test"]
---
This template was loaded from `.mokogitea/ISSUE_TEMPLATE/`.
If you can see this, the `.mokogitea` dot-folder feature is working.
@@ -57,12 +57,12 @@ jobs:
- name: Determine target repos
id: repos
env:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
GA_TOKEN: ${{ secrets.GA_TOKEN }}
run: |
API="${GITEA_URL}/api/v1"
# Platform/standards/infra repos to exclude
EXCLUDE="gitea-org-config org-profile gitea-private .mokogit-private MokoStandards mokoplatform MokoTesting"
EXCLUDE="gitea-org-config org-profile gitea-private .mokogitea-private MokoStandards mokoplatform MokoTesting"
EXCLUDE="$EXCLUDE MokoStandards-Template-Client MokoStandards-Template-Dolibarr MokoStandards-Template-Generic MokoStandards-Template-Joomla MokoDoliProjTemplate"
if [ -n "${{ inputs.repos }}" ]; then
@@ -74,7 +74,7 @@ jobs:
REPOS=""
while true; do
BATCH=$(curl -sS \
-H "Authorization: token ${MOKOGITEA_TOKEN}" \
-H "Authorization: token ${GA_TOKEN}" \
"${API}/orgs/${GITEA_ORG}/repos?page=${PAGE}&limit=50" \
| jq -r '.[].name // empty')
[ -z "$BATCH" ] && break
@@ -105,7 +105,7 @@ jobs:
- name: Apply protection rules
env:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
GA_TOKEN: ${{ secrets.GA_TOKEN }}
DRY_RUN: ${{ inputs.dry_run || 'false' }}
run: |
API="${GITEA_URL}/api/v1"
@@ -214,13 +214,13 @@ jobs:
ENCODED_NAME=$(echo "$NAME" | sed 's|/|%2F|g')
curl -sS -o /dev/null -w "" \
-X DELETE \
-H "Authorization: token ${MOKOGITEA_TOKEN}" \
-H "Authorization: token ${GA_TOKEN}" \
"${API}/repos/${GITEA_ORG}/${REPO}/branch_protections/${ENCODED_NAME}" 2>/dev/null || true
# Create rule
RESPONSE=$(curl -sS -w "\n%{http_code}" \
-X POST \
-H "Authorization: token ${MOKOGITEA_TOKEN}" \
-H "Authorization: token ${GA_TOKEN}" \
-H "Content-Type: application/json" \
-d "$RULE" \
"${API}/repos/${GITEA_ORG}/${REPO}/branch_protections")
@@ -1,66 +1,66 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGIT.Workflow
# INGROUP: mokocli.Release
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
# PATH: /.mokogit/workflows/auto-bump.yml
# VERSION: 09.02.00
# BRIEF: Auto patch-bump version on every push to dev (skips merge commits)
name: "Universal: Auto Version Bump"
on:
push:
branches:
- dev
- rc
- 'feature/**'
- 'patch/**'
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
MOKOGIT_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
permissions:
contents: write
jobs:
bump:
name: Version Bump
runs-on: release
if: >-
!contains(github.event.head_commit.message, '[skip ci]') &&
!contains(github.event.head_commit.message, '[skip bump]') &&
!startsWith(github.event.head_commit.message, 'Merge pull request')
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
token: ${{ secrets.MOKOGIT_TOKEN }}
fetch-depth: 1
- name: Setup mokocli tools
run: |
if ! command -v composer &> /dev/null; then
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer >/dev/null 2>&1
fi
if [ -d "/opt/mokocli/cli" ]; then
echo "MOKO_CLI=/opt/mokocli/cli" >> "$GITHUB_ENV"
else
git clone --depth 1 --branch main --quiet \
"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"
fi
- name: Bump version
run: |
php ${MOKO_CLI}/version_auto_bump.php \
--path . --branch "${GITHUB_REF_NAME}" \
--token "${{ secrets.MOKOGIT_TOKEN }}" \
--repo-url "https://x-access-token:${{ secrets.MOKOGIT_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: mokocli.Release
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
# PATH: /.mokogitea/workflows/auto-bump.yml
# VERSION: 09.02.00
# BRIEF: Auto patch-bump version on every push to dev (skips merge commits)
name: "Universal: Auto Version Bump"
on:
push:
branches:
- dev
- rc
- 'feature/**'
- 'patch/**'
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
permissions:
contents: write
jobs:
bump:
name: Version Bump
runs-on: release
if: >-
!contains(github.event.head_commit.message, '[skip ci]') &&
!contains(github.event.head_commit.message, '[skip bump]') &&
!startsWith(github.event.head_commit.message, 'Merge pull request')
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
token: ${{ secrets.MOKOGITEA_TOKEN }}
fetch-depth: 1
- name: Setup mokocli tools
run: |
if ! command -v composer &> /dev/null; then
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer >/dev/null 2>&1
fi
if [ -d "/opt/mokocli/cli" ]; then
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" \
/tmp/mokocli
cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet
echo "MOKO_CLI=/tmp/mokocli/cli" >> "$GITHUB_ENV"
fi
- name: Bump version
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"
@@ -3,16 +3,16 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGIT.Workflow
# DEFGROUP: Gitea.Workflow
# INGROUP: mokocli.Release
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/mokocli
# PATH: /templates/workflows/universal/auto-release.yml.template
# VERSION: 05.00.00
# BRIEF: Universal build & release detects platform from manifest.xml
#
# +=======================================================================+
# +========================================================================+
# | UNIVERSAL BUILD & RELEASE PIPELINE |
# +=======================================================================+
# +========================================================================+
# | |
# | Reads manifest.xml (joomla|dolibarr|generic) to branch logic. |
# | |
@@ -21,24 +21,15 @@
# | dolibarr: mod*.class.php, update.txt, dev version reset |
# | generic: README-only, no update stream |
# | |
# +=======================================================================+
# +========================================================================+
name: "Universal: Build & Release"
on:
pull_request:
types: [opened, synchronize, closed]
types: [opened, closed]
branches:
- main
paths-ignore:
- '.mokogit/workflows/**'
- '*.md'
- 'wiki/**'
- '.editorconfig'
- '.gitignore'
- '.gitattributes'
- '.gitmessage'
- 'LICENSE'
workflow_dispatch:
inputs:
action:
@@ -52,33 +43,32 @@ on:
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
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 }}
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 }}
permissions:
contents: write
jobs:
# ── PR Opened → Rename branch to RC and build RC release ─────────────────────────
# ── PR Opened → Rename branch to RC and build RC release ─────────────────────
promote-rc:
name: Promote to RC
runs-on: release
if: >-
(github.event.action == 'opened' && github.event.pull_request.merged != true) ||
(github.event.action == 'synchronize' && github.event.pull_request.merged != true) ||
(github.event_name == 'workflow_dispatch' && inputs.action == 'promote-rc')
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
token: ${{ secrets.MOKOGIT_TOKEN }}
token: ${{ secrets.MOKOGITEA_TOKEN }}
fetch-depth: 1
- name: Setup mokocli tools
env:
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
run: |
if [ -f /opt/mokocli/cli/version_bump.php ] && [ -f /opt/mokocli/vendor/autoload.php ]; then
@@ -99,68 +89,30 @@ jobs:
- name: Rename branch to rc
run: |
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 }}"
# Resolve the source branch HEAD commit.
SRC_JSON=$(curl -sf -H "$AUTH" "${API_BASE}/branches/${FROM}") \
|| { echo "::error::Source branch ${FROM} not found"; exit 1; }
SRC_SHA=$(printf '%s' "$SRC_JSON" | python3 -c "import sys, json; print(json.load(sys.stdin)['commit']['id'])" 2>/dev/null || true)
[ -n "$SRC_SHA" ] || { echo "::error::Could not resolve HEAD of ${FROM}"; exit 1; }
# Point rc at the source commit via git push. 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.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" \
|| { echo "::error::Failed to point rc at ${FROM} (${SRC_SHA}) via git push"; exit 1; }
echo "rc set to ${FROM} (${SRC_SHA})"
# Repoint the PR at rc, then delete the old source branch (non-fatal).
if [ -n "$PR" ]; then
curl -s -X PATCH -H "$AUTH" -H "Content-Type: application/json" \
"${API_BASE}/pulls/${PR}" -d '{"head":"rc"}' >/dev/null || true
fi
# Never delete permanent branches (dev/main/rc/...); only ephemeral feature branches.
case "$FROM" in
dev|main|master|rc|stable|production|release|develop|staging|beta|alpha)
echo "Keeping permanent branch ${FROM} (not deleting)" ;;
*)
curl -s -X DELETE -H "$AUTH" "${API_BASE}/branches/${FROM}" >/dev/null || true ;;
esac
echo "Renamed ${FROM} -> rc"
- 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.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?)"
php ${MOKO_CLI}/branch_rename.php \
--from "${{ github.event.pull_request.head.ref || 'dev' }}" --to rc \
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
--api-base "${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" \
--pr "${{ github.event.pull_request.number }}"
- name: Checkout rc and configure git
run: |
git fetch origin rc
git checkout rc
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 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"
- name: Publish RC release
continue-on-error: true
run: |
php ${MOKO_CLI}/release_publish.php \
--path . --stability rc --bump minor --branch rc \
--token "${{ secrets.MOKOGIT_TOKEN }}"
--token "${{ secrets.MOKOGITEA_TOKEN }}"
- name: Update RC release notes from CHANGELOG.md
continue-on-error: true
run: |
API_BASE="${MOKOGIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}"
TOKEN="${{ secrets.MOKOGIT_TOKEN }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
# Extract [Unreleased] section from changelog
NOTES=""
@@ -197,7 +149,7 @@ jobs:
echo "## Promoted to Release Candidate" >> $GITHUB_STEP_SUMMARY
echo "Branch renamed to rc, minor bump, RC release built" >> $GITHUB_STEP_SUMMARY
# ── Merged PR → Build & Release (or promote RC to stable) ─────────────────────────
# ── Merged PR → Build & Release (or promote RC to stable) ────────────────────
release:
name: Build & Release Pipeline
runs-on: release
@@ -209,14 +161,14 @@ jobs:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
token: ${{ secrets.MOKOGIT_TOKEN }}
token: ${{ secrets.MOKOGITEA_TOKEN }}
fetch-depth: 0
- name: Configure git for bot pushes
run: |
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 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"
- name: Check for merge conflict markers
run: |
@@ -233,7 +185,7 @@ jobs:
- name: Setup mokocli tools
env:
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_MIRROR_TOKEN }}"}}'
run: |
@@ -280,7 +232,7 @@ jobs:
fi
php ${MOKO_CLI}/release_publish.php \
--path . --stability stable ${BUMP_FLAG} --branch main \
--token "${{ secrets.MOKOGIT_TOKEN }}"
--token "${{ secrets.MOKOGITEA_TOKEN }}"
- name: "Read published version"
id: version
@@ -289,51 +241,15 @@ jobs:
VERSION=$(echo "$VERSION" | sed 's/-\(dev\|alpha\|beta\|rc\)$//')
[ -z "$VERSION" ] && VERSION="00.00.00" && echo "skip=true" >> "$GITHUB_OUTPUT"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
PLATFORM="${{ steps.platform.outputs.platform }}"
if [[ "$PLATFORM" == joomla* ]]; then
echo "tag=stable" >> "$GITHUB_OUTPUT"
echo "release_tag=stable" >> "$GITHUB_OUTPUT"
else
echo "tag=v${VERSION}" >> "$GITHUB_OUTPUT"
echo "release_tag=v${VERSION}" >> "$GITHUB_OUTPUT"
fi
echo "tag=stable" >> "$GITHUB_OUTPUT"
echo "release_tag=stable" >> "$GITHUB_OUTPUT"
echo "branch=main" >> "$GITHUB_OUTPUT"
echo "Published version: ${VERSION}"
- name: "Create semver tag for non-Joomla repos"
id: semver
if: |
steps.version.outputs.skip != 'true' &&
!startsWith(steps.platform.outputs.platform, 'joomla')
run: |
VERSION="${{ steps.version.outputs.version }}"
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}"
# Create the git tag via API
HTTP_CODE=$(curl -sf -o /dev/null -w "%{http_code}" \
-X POST -H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
"${API_BASE}/tags" \
-d "{\"tag_name\":\"${SEMVER_TAG}\",\"target\":\"main\",\"message\":\"Release ${VERSION}\"}" 2>/dev/null || echo "000")
if [ "$HTTP_CODE" = "201" ] || [ "$HTTP_CODE" = "200" ]; then
echo "Created semver tag: ${SEMVER_TAG}"
elif [ "$HTTP_CODE" = "409" ]; then
echo "Semver tag ${SEMVER_TAG} already exists (skipped)"
else
echo "::warning::Failed to create semver tag ${SEMVER_TAG} (HTTP ${HTTP_CODE})"
fi
echo "semver_tag=${SEMVER_TAG}" >> "$GITHUB_OUTPUT"
- name: Update release notes and promote changelog
run: |
API_BASE="${MOKOGIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}"
TOKEN="${{ secrets.MOKOGIT_TOKEN }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
# Get the stable release info (version and ID)
RELEASE_JSON=$(curl -sf -H "Authorization: token ${TOKEN}" \
@@ -401,10 +317,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="${MOKOGIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
php ${MOKO_CLI}/release_mirror.php \
--version "$VERSION" --tag "$RELEASE_TAG" \
--token "${{ secrets.MOKOGIT_TOKEN }}" --api-base "$API_BASE" \
--token "${{ secrets.MOKOGITEA_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
@@ -430,8 +346,8 @@ jobs:
if: steps.version.outputs.skip != 'true'
continue-on-error: true
run: |
API_BASE="${MOKOGIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}"
TOKEN="${{ secrets.MOKOGIT_TOKEN }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
# Delete rc branch (ephemeral — created by promote-rc)
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
@@ -454,8 +370,8 @@ jobs:
if: steps.version.outputs.skip != 'true'
continue-on-error: true
run: |
API_BASE="${MOKOGIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}"
TOKEN="${{ secrets.MOKOGIT_TOKEN }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
BRANCH_NAME="version/${VERSION}"
MAIN_SHA=$(git rev-parse HEAD)
@@ -475,9 +391,9 @@ jobs:
if: steps.version.outputs.skip != 'true'
continue-on-error: true
run: |
API_BASE="${MOKOGIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
php ${MOKO_CLI}/version_reset_dev.php \
--token "${{ secrets.MOKOGIT_TOKEN }}" --api-base "${API_BASE}" \
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "${API_BASE}" \
--branch dev --path . 2>&1 || true
# -- Summary --------------------------------------------------------------
@@ -501,5 +417,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](${MOKOGIT_URL}/${GIT_ORG}/${GIT_REPO}/releases/tag/${{ steps.version.outputs.tag }}) |" >> $GITHUB_STEP_SUMMARY
echo "| Release | [View](${GITEA_URL}/${GITEA_ORG}/${GITEA_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: MokoGIT.Workflow
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
# PATH: /.mokogit/workflows/branch-cleanup.yml
# PATH: /.mokogitea/workflows/branch-cleanup.yml
# VERSION: 01.00.00
# BRIEF: Delete feature branches after PR merge
@@ -36,7 +36,7 @@ jobs:
ENCODED=$(php -r "echo rawurlencode('${BRANCH}');")
STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X DELETE \
-H "Authorization: token ${{ secrets.MOKOGIT_TOKEN }}" \
-H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \
"${API}/${ENCODED}" 2>/dev/null || true)
if [ "$STATUS" = "204" ]; then
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGIT.Workflow
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.CI
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.gitea/workflows/ci-generic.yml
@@ -13,12 +13,6 @@
name: "Generic: Project CI"
on:
pull_request:
branches:
- main
- dev
- dev/**
- rc/**
workflow_dispatch:
permissions:
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGIT.Workflow
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Maintenance
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards
# PATH: /.gitea/workflows/cleanup.yml
@@ -21,7 +21,7 @@ permissions:
contents: write
env:
MOKOGIT_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
GITEA_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.MOKOGIT_TOKEN }}
token: ${{ secrets.GA_TOKEN }}
- name: Delete merged branches
env:
MOKOGIT_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
GA_TOKEN: ${{ secrets.GA_TOKEN }}
run: |
echo "=== Merged Branch Cleanup ==="
API="${MOKOGIT_URL}/api/v1/repos/${{ github.repository }}"
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
# List branches via API
BRANCHES=$(curl -sS -H "Authorization: token ${MOKOGIT_TOKEN}" \
BRANCHES=$(curl -sS -H "Authorization: token ${GA_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 ${MOKOGIT_TOKEN}" \
curl -sS -X DELETE -H "Authorization: token ${GA_TOKEN}" \
"${API}/branches/${BRANCH}" 2>/dev/null || true
DELETED=$((DELETED + 1))
fi
@@ -66,20 +66,20 @@ jobs:
- name: Clean old workflow runs
env:
MOKOGIT_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
GA_TOKEN: ${{ secrets.GA_TOKEN }}
run: |
echo "=== Workflow Run Cleanup ==="
API="${MOKOGIT_URL}/api/v1/repos/${{ github.repository }}"
API="${GITEA_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 ${MOKOGIT_TOKEN}" \
RUNS=$(curl -sS -H "Authorization: token ${GA_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 ${MOKOGIT_TOKEN}" \
curl -sS -X DELETE -H "Authorization: token ${GA_TOKEN}" \
"${API}/actions/runs/${RUN_ID}" 2>/dev/null || true
DELETED=$((DELETED + 1))
done
+76
View File
@@ -0,0 +1,76 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
name: "Publish to Composer"
on:
push:
tags:
- 'v*'
- '[0-9]*.[0-9]*.[0-9]*'
release:
types: [published]
workflow_dispatch:
env:
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
jobs:
publish:
name: Publish Package
runs-on: ubuntu-latest
if: >-
!contains(github.event.head_commit.message, '[skip ci]') &&
!contains(github.event.head_commit.message, '[skip publish]')
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup PHP
run: |
if ! command -v php &> /dev/null; then
sudo apt-get update -qq
sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer >/dev/null 2>&1
fi
- name: Install dependencies
run: composer install --no-dev --no-interaction --prefer-dist --quiet
- name: Determine version
id: version
run: |
VERSION=$(php -r "echo json_decode(file_get_contents('composer.json'))->version;")
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "Package version: ${VERSION}"
# Gitea 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
run: |
echo "Gitea Composer registry auto-publishes from tags."
echo "Package available at: ${GITEA_URL}/api/packages/MokoConsulting/composer"
echo "Install: composer require mokoconsulting/mokocli"
# Packagist — notify of new version
- name: Notify Packagist
if: secrets.PACKAGIST_TOKEN != ''
run: |
VERSION="${{ steps.version.outputs.version }}"
echo "Notifying Packagist of version ${VERSION}..."
curl -sf -X POST \
-H "Content-Type: application/json" \
-d '{"repository":{"url":"https://git.mokoconsulting.tech/MokoConsulting/mokocli"}}' \
"https://packagist.org/api/update-package?username=mokoconsulting&apiToken=${{ secrets.PACKAGIST_TOKEN }}" \
&& echo "Packagist notified" \
|| echo "::warning::Packagist notification failed (package may not be registered yet)"
- name: Summary
run: |
VERSION="${{ steps.version.outputs.version }}"
echo "## Composer Package Published" >> $GITHUB_STEP_SUMMARY
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 "| Packagist | \`composer require mokoconsulting/mokocli\` |" >> $GITHUB_STEP_SUMMARY
+126
View File
@@ -0,0 +1,126 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Deploy
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
# PATH: /templates/workflows/joomla/deploy-manual.yml.template
# VERSION: 04.07.00
# BRIEF: Manual SFTP deploy to dev server for Joomla repos
name: "Universal: Deploy to Dev (Manual)"
on:
workflow_dispatch:
inputs:
clear_remote:
description: 'Delete all remote files before uploading'
required: false
default: 'false'
type: boolean
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
permissions:
contents: read
jobs:
deploy:
name: SFTP Deploy to Dev
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Setup PHP
run: |
php -v && composer --version
- name: Setup MokoStandards tools
env:
GA_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
MOKO_CLONE_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
MOKO_CLONE_HOST: ${{ secrets.GA_TOKEN && 'git.mokoconsulting.tech/MokoConsulting' || 'github.com/mokoconsulting-tech' }}
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GA_TOKEN || github.token }}"}}'
run: |
git clone --depth 1 --branch main --quiet \
"https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoStandards-API.git" \
/tmp/mokostandards-api 2>/dev/null || true
if [ -d "/tmp/mokostandards-api" ] && [ -f "/tmp/mokostandards-api/composer.json" ]; then
cd /tmp/mokostandards-api && composer install --no-dev --no-interaction --quiet 2>/dev/null || true
fi
- name: Check FTP configuration
id: check
env:
HOST: ${{ vars.DEV_FTP_HOST }}
PATH_VAR: ${{ vars.DEV_FTP_PATH }}
PORT: ${{ vars.DEV_FTP_PORT }}
run: |
if [ -z "$HOST" ] || [ -z "$PATH_VAR" ]; then
echo "DEV_FTP_HOST or DEV_FTP_PATH not configured -- cannot deploy"
echo "skip=true" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "skip=false" >> "$GITHUB_OUTPUT"
echo "host=$HOST" >> "$GITHUB_OUTPUT"
REMOTE="${PATH_VAR%/}"
echo "remote=$REMOTE" >> "$GITHUB_OUTPUT"
[ -z "$PORT" ] && PORT="22"
echo "port=$PORT" >> "$GITHUB_OUTPUT"
- name: Deploy via SFTP
if: steps.check.outputs.skip != 'true'
env:
SFTP_KEY: ${{ secrets.DEV_FTP_KEY }}
SFTP_PASS: ${{ secrets.DEV_FTP_PASSWORD }}
SFTP_USER: ${{ vars.DEV_FTP_USERNAME }}
run: |
SOURCE_DIR="src"
[ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs"
[ ! -d "$SOURCE_DIR" ] && { echo "No src/ or htdocs/ -- nothing to deploy"; exit 0; }
printf '{"host":"%s","port":%s,"username":"%s","remotePath":"%s"' \
"${{ steps.check.outputs.host }}" "${{ steps.check.outputs.port }}" "$SFTP_USER" "${{ steps.check.outputs.remote }}" \
> /tmp/sftp-config.json
if [ -n "$SFTP_KEY" ]; then
echo "$SFTP_KEY" > /tmp/deploy_key
chmod 600 /tmp/deploy_key
printf ',"privateKeyPath":"/tmp/deploy_key"}' >> /tmp/sftp-config.json
else
printf ',"password":"%s"}' "$SFTP_PASS" >> /tmp/sftp-config.json
fi
DEPLOY_ARGS=(--path . --src-dir "$SOURCE_DIR" --config /tmp/sftp-config.json)
[ "${{ inputs.clear_remote }}" = "true" ] && DEPLOY_ARGS+=(--clear-remote)
PLATFORM=$(php /tmp/mokostandards-api/cli/platform_detect.php --path . 2>/dev/null || true)
if [ "$PLATFORM" = "waas-component" ] && [ -f "/tmp/mokostandards-api/deploy/deploy-joomla.php" ]; then
php /tmp/mokostandards-api/deploy/deploy-joomla.php "${DEPLOY_ARGS[@]}"
else
php /tmp/mokostandards-api/deploy/deploy-sftp.php "${DEPLOY_ARGS[@]}"
fi
rm -f /tmp/deploy_key /tmp/sftp-config.json
- name: Summary
if: always()
run: |
if [ "${{ steps.check.outputs.skip }}" = "true" ]; then
echo "### Deploy Skipped -- FTP not configured" >> $GITHUB_STEP_SUMMARY
else
echo "### Manual Dev Deploy Complete" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| Host | \`${{ steps.check.outputs.host }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Remote | \`${{ steps.check.outputs.remote }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Clear | ${{ inputs.clear_remote }} |" >> $GITHUB_STEP_SUMMARY
fi
+151
View File
@@ -0,0 +1,151 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
# BRIEF: Build MokoGitea Docker image, push to registry, and deploy
name: Deploy MokoGitea
on:
push:
branches:
- main
workflow_dispatch:
inputs:
version:
description: 'Version tag'
required: true
default: 'latest'
environment:
description: 'Target environment'
required: true
default: 'dev'
type: choice
options:
- dev
- production
concurrency:
group: deploy-mokogitea
cancel-in-progress: false
env:
REGISTRY: git.mokoconsulting.tech
IMAGE: mokoconsulting/mokogitea
DEPLOY_HOST: git.mokoconsulting.tech
DEPLOY_PORT: 2918
DEPLOY_USER: mokoconsulting
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout source (for version detection)
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Determine settings
id: config
run: |
if [ "${{ github.event_name }}" = "push" ]; then
VERSION=$(git describe --tags --always 2>/dev/null || echo "dev-$(git rev-parse --short HEAD)")
ENV="production"
else
VERSION="${{ github.event.inputs.version }}"
ENV="${{ github.event.inputs.environment }}"
fi
if [ "$ENV" = "production" ]; then
echo "compose_dir=/opt/gitea" >> $GITHUB_OUTPUT
echo "container=mokogitea" >> $GITHUB_OUTPUT
echo "source_dir=/opt/gitea/source" >> $GITHUB_OUTPUT
echo "branch=main" >> $GITHUB_OUTPUT
echo "tag=$VERSION" >> $GITHUB_OUTPUT
else
echo "compose_dir=/opt/gitea-dev" >> $GITHUB_OUTPUT
echo "container=mokogitea-dev" >> $GITHUB_OUTPUT
echo "source_dir=/opt/gitea-dev/source" >> $GITHUB_OUTPUT
echo "branch=dev" >> $GITHUB_OUTPUT
echo "tag=$VERSION-dev" >> $GITHUB_OUTPUT
fi
- name: Write deploy key
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
run: |
mkdir -p ~/.ssh
echo "$DEPLOY_KEY" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
- name: Build and deploy via SSH
env:
REGISTRY_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
TAG: ${{ steps.config.outputs.tag }}
BRANCH: ${{ steps.config.outputs.branch }}
SOURCE_DIR: ${{ steps.config.outputs.source_dir }}
COMPOSE_DIR: ${{ steps.config.outputs.compose_dir }}
CONTAINER: ${{ steps.config.outputs.container }}
run: |
HEALTH_FMT='${{ '{{' }}.State.Health.Status${{ '}}' }}'
IMAGE_FMT='Image: ${{ '{{' }}.Config.Image${{ '}}' }}'
ssh -i ~/.ssh/deploy_key -p ${{ env.DEPLOY_PORT }} \
-o ConnectTimeout=30 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
-o ServerAliveInterval=30 -o ServerAliveCountMax=10 \
${{ env.DEPLOY_USER }}@${{ env.DEPLOY_HOST }} bash -s <<DEPLOY_EOF
set -e
echo 'SSH connected'
echo 'Cleaning Docker build cache...'
docker builder prune -af 2>/dev/null || true
docker image prune -af 2>/dev/null || true
free -m | head -3
echo 'Pulling source...'
if [ ! -d $SOURCE_DIR/.git ]; then
git clone -b $BRANCH https://git.mokoconsulting.tech/MokoConsulting/MokoGitea-Fork.git $SOURCE_DIR
fi
cd $SOURCE_DIR
# Ensure remote points to MokoGitea-Fork (not the upstream fork)
git remote set-url origin https://git.mokoconsulting.tech/MokoConsulting/MokoGitea-Fork.git 2>/dev/null || true
git fetch origin $BRANCH
git reset --hard origin/$BRANCH
echo 'Building Docker image...'
docker build --no-cache --build-arg GOFLAGS='-p 1' \
--tag ${{ env.REGISTRY }}/${{ env.IMAGE }}:$TAG \
--tag ${{ env.REGISTRY }}/${{ env.IMAGE }}:latest \
-f Dockerfile .
echo 'Pushing to registry...'
echo '$REGISTRY_TOKEN' | docker login ${{ env.REGISTRY }} -u ${{ env.DEPLOY_USER }} --password-stdin
docker push ${{ env.REGISTRY }}/${{ env.IMAGE }}:$TAG
docker push ${{ env.REGISTRY }}/${{ env.IMAGE }}:latest
echo 'Restarting container...'
cd $COMPOSE_DIR
sed -i 's|${{ env.IMAGE }}:[^ ]*|${{ env.IMAGE }}:$TAG|' docker-compose.yml
docker compose up -d $CONTAINER
echo 'Health check...'
for i in 1 2 3 4 5 6 7 8; do
sleep 15
if docker inspect --format='$HEALTH_FMT' $CONTAINER 2>/dev/null | grep -q healthy; then
echo 'Container healthy!'
docker inspect --format='$IMAGE_FMT' $CONTAINER
exit 0
fi
echo "Waiting... (attempt \$i/8)"
done
echo 'Health check failed'
docker logs $CONTAINER --tail 20
exit 1
DEPLOY_EOF
- name: Verify
run: |
sleep 5
curl -sf https://${{ env.DEPLOY_HOST }}/api/healthz && echo " API healthy"
- name: Notify on failure
if: failure()
run: echo "::error::Deploy failed for ${{ steps.config.outputs.tag }}"
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGIT.Workflow
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Security
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API
# PATH: /templates/workflows/gitleaks.yml.template
@@ -34,7 +34,7 @@ permissions:
env:
NTFY_URL: ${{ vars.NTFY_URL || 'https://ntfy.mokoconsulting.tech' }}
NTFY_TOPIC: ${{ vars.NTFY_TOPIC || 'git-security' }}
NTFY_TOPIC: ${{ vars.NTFY_TOPIC || 'gitea-security' }}
jobs:
gitleaks:
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGIT.Workflow
# DEFGROUP: Gitea.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:
MOKOGIT_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
GITEA_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.MOKOGIT_TOKEN }}"
API="${MOKOGIT_URL}/api/v1/repos/${{ github.repository }}"
TOKEN="${{ secrets.GA_TOKEN }}"
API="${GITEA_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="${MOKOGIT_URL}/${{ github.repository }}"
REPO_URL="${GITEA_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,7 +3,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGIT.Workflow
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Notifications
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards
# PATH: /.gitea/workflows/notify.yml
@@ -26,7 +26,7 @@ permissions:
env:
NTFY_URL: ${{ vars.NTFY_URL || 'https://ntfy.mokoconsulting.tech' }}
NTFY_TOPIC: ${{ vars.NTFY_TOPIC || 'git-releases' }}
NTFY_TOPIC: ${{ vars.NTFY_TOPIC || 'gitea-releases' }}
jobs:
notify:
+51
View File
@@ -0,0 +1,51 @@
name: Publish MCP to npm
on:
push:
branches: [main]
paths:
- '.mokogitea/mcp/**'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
- name: Install and build
working-directory: .mokogitea/mcp
run: |
npm ci
npx tsc
- name: Check version change
id: version
working-directory: .mokogitea/mcp
run: |
LOCAL_VERSION=$(node -p "require('./package.json').version")
NPM_VERSION=$(npm view @mokoconsulting/mokogitea-mcp version 2>/dev/null || echo "0.0.0")
if [ "$LOCAL_VERSION" != "$NPM_VERSION" ]; then
echo "changed=true" >> $GITHUB_OUTPUT
echo "Version changed: $NPM_VERSION -> $LOCAL_VERSION"
else
echo "changed=false" >> $GITHUB_OUTPUT
echo "Version unchanged: $LOCAL_VERSION"
fi
- name: Publish to npm
if: steps.version.outputs.changed == 'true'
working-directory: .mokogitea/mcp
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Publish to Gitea registry
if: steps.version.outputs.changed == 'true'
working-directory: .mokogitea/mcp
run: |
npm publish --registry ${{ github.server_url }}/api/packages/${{ github.repository_owner }}/npm/ \
--//$(echo "${{ github.server_url }}" | sed 's|https://||')/api/packages/${{ github.repository_owner }}/npm/:_authToken=${{ secrets.MOKOGITEA_TOKEN }}
File diff suppressed because it is too large Load Diff
+170
View File
@@ -0,0 +1,170 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
# BRIEF: Auto-build RC release on PR to main, update RC update stream
name: "PR RC Release"
on:
pull_request:
types: [opened, synchronize]
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
REGISTRY: code.mokoconsulting.tech
IMAGE: mokoconsulting/mokogitea
permissions:
contents: write
jobs:
rc-release:
name: Build RC Release
runs-on: ubuntu-latest
steps:
- name: Check target branch
id: guard
env:
BASE_BRANCH: ${{ github.base_ref }}
run: |
echo "PR target: ${BASE_BRANCH}"
if [ "$BASE_BRANCH" != "main" ]; then
echo "skip=true" >> "$GITHUB_OUTPUT"
echo "Skipping RC — only for PRs targeting main"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi
- name: Checkout PR branch
if: steps.guard.outputs.skip != 'true'
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- name: Determine RC version
if: steps.guard.outputs.skip != 'true'
id: version
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
BASE_VERSION=$(sed -n 's/.*<version>\(.*\)<\/version>.*/\1/p' updates.xml | head -1)
[ -z "$BASE_VERSION" ] && BASE_VERSION="04.00.00"
RC_VERSION="${BASE_VERSION}-rc.${PR_NUMBER}"
RC_TAG="v1.26.1-moko.${RC_VERSION}"
echo "version=$RC_VERSION" >> "$GITHUB_OUTPUT"
echo "tag=$RC_TAG" >> "$GITHUB_OUTPUT"
echo "RC version: $RC_VERSION (tag: $RC_TAG)"
- name: Update updates.xml RC channel
if: steps.guard.outputs.skip != 'true'
env:
RC_VERSION: ${{ steps.version.outputs.version }}
RC_TAG: ${{ steps.version.outputs.tag }}
PR_URL: ${{ github.event.pull_request.html_url }}
PR_NUM: ${{ github.event.pull_request.number }}
run: |
DOCKER_TAG="${REGISTRY}/${IMAGE}:${RC_TAG}"
python3 << 'PYEOF'
import os, re
rc_version = os.environ["RC_VERSION"]
rc_tag = os.environ["RC_TAG"]
pr_url = os.environ["PR_URL"]
pr_num = os.environ["PR_NUM"]
docker_tag = os.environ["REGISTRY"] + "/" + os.environ["IMAGE"] + ":" + rc_tag
entry = f""" <update>
<name>MokoGitea</name>
<description>MokoGitea RC from PR #{pr_num}</description>
<element>mokogitea</element>
<type>application</type>
<version>{rc_version}</version>
<client>server</client>
<tags><tag>rc</tag></tags>
<infourl title="MokoGitea RC">{pr_url}</infourl>
<downloads>
<downloadurl type="full" format="docker">{docker_tag}</downloadurl>
</downloads>
<sha256></sha256>
<targetplatform name="mokogitea" version="((1\\.25\\.)|(1\\.26\\.))" />
<maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
</update>"""
content = open("updates.xml").read()
# Remove existing RC entry
content = re.sub(
r"\s*<update>[\s\S]*?<tag>rc</tag>[\s\S]*?</update>",
"",
content,
)
# Insert before </updates>
content = content.replace("</updates>", entry + "\n</updates>")
open("updates.xml", "w").write(content)
print(f"Updated updates.xml with RC entry: {rc_version}")
PYEOF
- name: Create RC release
if: steps.guard.outputs.skip != 'true'
env:
GITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
RC_TAG: ${{ steps.version.outputs.tag }}
RC_VERSION: ${{ steps.version.outputs.version }}
PR_TITLE: ${{ github.event.pull_request.title }}
PR_URL: ${{ github.event.pull_request.html_url }}
PR_NUMBER: ${{ github.event.pull_request.number }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
API_BASE: https://${{ env.REGISTRY }}/api/v1/repos/${{ github.repository }}
run: |
# Delete existing RC release/tag if present
curl -s -X DELETE -H "Authorization: token ${GITEA_TOKEN}" \
"${API_BASE}/releases/tags/${RC_TAG}" 2>/dev/null || true
curl -s -X DELETE -H "Authorization: token ${GITEA_TOKEN}" \
"${API_BASE}/tags/${RC_TAG}" 2>/dev/null || true
# Create prerelease
python3 << PYEOF
import json, os, urllib.request
api = os.environ["API_BASE"]
token = os.environ["GITEA_TOKEN"]
payload = json.dumps({
"tag_name": os.environ["RC_TAG"],
"target_commitish": os.environ["HEAD_SHA"],
"name": f"RC: {os.environ['PR_TITLE']}",
"body": f"Release candidate from PR #{os.environ['PR_NUMBER']}\n\nPR: {os.environ['PR_URL']}\nDocker: docker pull {os.environ['REGISTRY']}/{os.environ['IMAGE']}:{os.environ['RC_TAG']}",
"draft": False,
"prerelease": True,
}).encode()
req = urllib.request.Request(
f"{api}/releases",
data=payload,
headers={
"Authorization": f"token {token}",
"Content-Type": "application/json",
},
method="POST",
)
with urllib.request.urlopen(req) as resp:
result = json.loads(resp.read())
print(f"Created RC release: {result.get('tag_name')}")
PYEOF
- name: Commit updates.xml
if: steps.guard.outputs.skip != 'true'
env:
GITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
HEAD_REF: ${{ github.event.pull_request.head.ref }}
PR_NUM: ${{ github.event.pull_request.number }}
run: |
git config user.name "MokoGitea Bot"
git config user.email "deploy@mokoconsulting.tech"
git add updates.xml
if git diff --cached --quiet; then
echo "No changes to updates.xml"
else
git commit -m "chore(ci): update RC stream for PR #${PR_NUM}"
git push origin "HEAD:${HEAD_REF}" || echo "Push failed"
fi
@@ -3,11 +3,11 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGIT.Workflow
# DEFGROUP: Gitea.Workflow
# INGROUP: mokocli.Release
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
# PATH: /templates/workflows/universal/pre-release.yml.template
# VERSION: 05.02.00
# VERSION: 05.01.00
# BRIEF: Auto pre-release on push to dev/alpha/beta/rc branches
name: "Universal: Pre-Release"
@@ -40,9 +40,9 @@ permissions:
contents: write
env:
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 }}
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:
@@ -57,17 +57,12 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.MOKOGIT_TOKEN }}
token: ${{ secrets.MOKOGITEA_TOKEN }}
ref: ${{ github.ref_name }}
submodules: recursive
- name: Update submodules to main
run: |
git submodule foreach --quiet 'git checkout main && git pull --quiet origin main' 2>/dev/null || true
- name: Setup mokocli tools
env:
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
run: |
# Use pre-installed /opt/mokocli if available (updated by cron every 6h)
@@ -93,20 +88,8 @@ jobs:
php ${MOKO_CLI}/platform_detect.php --path . --github-output 2>/dev/null || true
php ${MOKO_CLI}/manifest_read.php --path . --github-output
- name: Check platform eligibility (Joomla only)
id: eligibility
run: |
PLATFORM="${{ steps.platform.outputs.platform }}"
if [[ "$PLATFORM" == joomla* ]] || [[ "$PLATFORM" == "joomla" ]]; then
echo "proceed=true" >> "$GITHUB_OUTPUT"
else
echo "proceed=false" >> "$GITHUB_OUTPUT"
echo "::notice::Platform '$PLATFORM' — non-Joomla, skipping pre-release auto-bump"
fi
- name: Resolve metadata and bump version
id: meta
if: steps.eligibility.outputs.proceed == 'true'
run: |
# Auto-detect stability from branch name on push, or use input on dispatch
if [ "${{ github.event_name }}" = "push" ]; then
@@ -152,9 +135,9 @@ jobs:
fi
# Commit version bump
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 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]"
@@ -164,12 +147,12 @@ jobs:
# Auto-detect element via manifest_element.php
php ${MOKO_CLI}/manifest_element.php \
--path . --version "$VERSION" --stability "$STABILITY" \
--repo "${GIT_REPO}" --github-output
--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 "${GIT_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
[ -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"
@@ -183,22 +166,20 @@ jobs:
- name: Create release
id: release
if: steps.eligibility.outputs.proceed == 'true'
run: |
TAG="${{ steps.meta.outputs.tag }}"
VERSION="${{ steps.meta.outputs.version }}"
API_BASE="${GIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
php ${MOKO_CLI}/release_create.php \
--path . --version "$VERSION" --tag "$TAG" \
--token "${{ secrets.MOKOGIT_TOKEN }}" --api-base "$API_BASE" \
--repo "${GIT_REPO}" --branch "${{ github.ref_name }}" --prerelease
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
--repo "${GITEA_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="${GIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}"
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
@@ -209,7 +190,7 @@ jobs:
fi
# Update release body via API
RELEASE_ID=$(curl -sf -H "Authorization: token ${{ secrets.MOKOGIT_TOKEN }}" \
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
@@ -221,7 +202,7 @@ jobs:
'${API_BASE}/releases/${RELEASE_ID}',
data=payload, method='PATCH',
headers={
'Authorization': 'token ${{ secrets.MOKOGIT_TOKEN }}',
'Authorization': 'token ${{ secrets.MOKOGITEA_TOKEN }}',
'Content-Type': 'application/json'
})
urllib.request.urlopen(req)
@@ -231,25 +212,23 @@ jobs:
- name: Build package and upload
id: package
if: steps.eligibility.outputs.proceed == 'true'
run: |
VERSION="${{ steps.meta.outputs.version }}"
TAG="${{ steps.meta.outputs.tag }}"
API_BASE="${GIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
php ${MOKO_CLI}/release_package.php \
--path . --version "$VERSION" --tag "$TAG" \
--token "${{ secrets.MOKOGIT_TOKEN }}" --api-base "$API_BASE" \
--repo "${GIT_REPO}" --output /tmp || true
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
--repo "${GITEA_REPO}" --output /tmp || true
# updates.xml is generated dynamically by MokoGIT license server
# 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)"
if: steps.eligibility.outputs.proceed == 'true'
continue-on-error: true
run: |
API_BASE="${GIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}"
TOKEN="${{ secrets.MOKOGIT_TOKEN }}"
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 }}" \
@@ -3,10 +3,10 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGIT.Workflow
# DEFGROUP: Gitea.Workflow
# INGROUP: mokocli.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
# PATH: /.mokogit/workflows/rc-revert.yml
# PATH: /.mokogitea/workflows/rc-revert.yml
# VERSION: 09.23.00
# BRIEF: Rename rc/ branch back to dev/ when PR is closed without merge
@@ -29,20 +29,12 @@ jobs:
steps:
- name: Rename branch
env:
BRANCH: ${{ github.event.pull_request.head.ref }}
REPO: ${{ github.repository }}
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.
if ! printf '%s' "$BRANCH" | grep -Eq '^rc/[A-Za-z0-9._/-]+$'; then
echo "::error::Refusing unsafe branch name: $BRANCH"; exit 1
fi
BRANCH="${{ github.event.pull_request.head.ref }}"
SUFFIX="${BRANCH#rc/}"
DEV_BRANCH="dev/${SUFFIX}"
API="${GIT_URL}/api/v1/repos/${REPO}/branches"
API="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}/api/v1/repos/${{ github.repository }}/branches"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
# Create dev/ branch from rc/ branch
STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X POST \
@@ -50,22 +42,25 @@ jobs:
-H "Content-Type: application/json" \
-d "{\"new_branch_name\": \"${DEV_BRANCH}\", \"old_branch_name\": \"${BRANCH}\"}" \
"${API}" 2>/dev/null || true)
if [ "$STATUS" = "201" ]; then
echo "Created branch: ${DEV_BRANCH}" >> "$GITHUB_STEP_SUMMARY"
echo "Created branch: ${DEV_BRANCH}" >> $GITHUB_STEP_SUMMARY
else
echo "::error::Failed to create ${DEV_BRANCH} from ${BRANCH} (HTTP ${STATUS})"; exit 1
echo "::error::Failed to create ${DEV_BRANCH} from ${BRANCH} (HTTP ${STATUS})"
exit 1
fi
# Read BRANCH from the environment inside PHP (getenv, no string interpolation -> no PHP injection)
ENCODED=$(php -r 'echo rawurlencode(getenv("BRANCH"));')
# Delete rc/ branch
ENCODED=$(php -r "echo rawurlencode('${BRANCH}');")
STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X DELETE \
-H "Authorization: token ${TOKEN}" \
"${API}/${ENCODED}" 2>/dev/null || true)
if [ "$STATUS" = "204" ]; then
echo "Deleted branch: ${BRANCH}" >> "$GITHUB_STEP_SUMMARY"
echo "Deleted branch: ${BRANCH}" >> $GITHUB_STEP_SUMMARY
else
echo "::warning::Failed to delete ${BRANCH} (HTTP ${STATUS})"
fi
echo "### RC Reverted" >> "$GITHUB_STEP_SUMMARY"
echo "${BRANCH} → ${DEV_BRANCH}" >> "$GITHUB_STEP_SUMMARY"
echo "### RC Reverted" >> $GITHUB_STEP_SUMMARY
echo "${BRANCH} → ${DEV_BRANCH}" >> $GITHUB_STEP_SUMMARY
File diff suppressed because it is too large Load Diff
+82
View File
@@ -0,0 +1,82 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Security
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards
# PATH: /.gitea/workflows/security-audit.yml
# VERSION: 01.00.00
# BRIEF: Dependency vulnerability scanning for composer and npm packages
name: "Universal: Security Audit"
on:
schedule:
- cron: '0 6 * * 1' # Weekly on Monday at 06:00 UTC
pull_request:
branches:
- main
paths:
- 'composer.json'
- 'composer.lock'
- 'package.json'
- 'package-lock.json'
workflow_dispatch:
permissions:
contents: read
env:
NTFY_URL: ${{ vars.NTFY_URL || 'https://ntfy.mokoconsulting.tech' }}
NTFY_TOPIC: ${{ vars.NTFY_TOPIC || 'gitea-security' }}
jobs:
audit:
name: Dependency Audit
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Composer audit
if: hashFiles('composer.lock') != ''
run: |
echo "=== Composer Security Audit ==="
if ! command -v composer &> /dev/null; then
sudo apt-get update -qq
sudo apt-get install -y -qq php-cli composer >/dev/null 2>&1
fi
composer audit --format=plain 2>&1 | tee /tmp/composer-audit.txt
RESULT=$?
if [ $RESULT -ne 0 ]; then
echo "::warning::Composer vulnerabilities found"
echo "composer_vulnerable=true" >> "$GITHUB_ENV"
else
echo "No known vulnerabilities in composer dependencies"
fi
- name: NPM audit
if: hashFiles('package-lock.json') != ''
run: |
echo "=== NPM Security Audit ==="
npm audit --production 2>&1 | tee /tmp/npm-audit.txt || true
if npm audit --production 2>&1 | grep -q "found 0 vulnerabilities"; then
echo "No known vulnerabilities in npm dependencies"
else
echo "::warning::NPM vulnerabilities found"
echo "npm_vulnerable=true" >> "$GITHUB_ENV"
fi
- name: Notify on vulnerabilities
if: env.composer_vulnerable == 'true' || env.npm_vulnerable == 'true'
run: |
REPO="${{ github.event.repository.name }}"
curl -sS \
-H "Title: ${REPO} has vulnerable dependencies" \
-H "Tags: lock,warning" \
-H "Priority: high" \
-d "Security audit found vulnerabilities. Review dependency updates." \
"${NTFY_URL}/${NTFY_TOPIC}" || true
+12
View File
@@ -0,0 +1,12 @@
# Test workflow to verify .mokogitea/ directory is discovered
name: Test .mokogitea workflows
on:
workflow_dispatch:
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Verify .mokogitea
run: echo "This workflow ran from .mokogitea/workflows/ — feature works!"
+167
View File
@@ -0,0 +1,167 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
# BRIEF: Sync upstream Gitea bug fixes into MokoGitea issue tracker
name: Upstream Bug Sync
on:
schedule:
- cron: '0 8 * * *' # daily at 08:00 UTC
workflow_dispatch:
inputs:
days_back:
description: 'How many days back to scan (default: 7)'
required: false
default: '7'
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Sync upstream bugs
env:
GH_TOKEN: ${{ secrets.GH_MIRROR_TOKEN }}
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
MOKOGITEA_URL: https://code.mokoconsulting.tech
MOKOGITEA_REPO: MokoConsulting/MokoGitea
UPSTREAM_BRANCH: release/v1.26
DAYS_BACK: ${{ github.event.inputs.days_back || '7' }}
run: |
python3 << 'PYEOF'
import json, os, re, sys, urllib.parse, urllib.request
from datetime import datetime, timedelta, timezone
GH_TOKEN = os.environ["GH_TOKEN"]
MOKO_TOKEN = os.environ["MOKOGITEA_TOKEN"]
MOKO_URL = os.environ["MOKOGITEA_URL"]
MOKO_REPO = os.environ["MOKOGITEA_REPO"]
BRANCH = os.environ["UPSTREAM_BRANCH"]
DAYS = int(os.environ.get("DAYS_BACK", "7"))
# Label IDs in MokoGitea
LABELS = {
"type_bug": 5757, "upstream": 5758, "security": 5032,
"critical": 5018, "high": 5019, "medium": 5020, "low": 5021,
}
def gh_get(url):
req = urllib.request.Request(url, headers={
"Authorization": f"token {GH_TOKEN}",
"Accept": "application/vnd.github.v3+json",
})
with urllib.request.urlopen(req) as r:
return json.loads(r.read())
def moko_get(path):
req = urllib.request.Request(f"{MOKO_URL}/api/v1/{path}", headers={
"Authorization": f"token {MOKO_TOKEN}",
})
with urllib.request.urlopen(req) as r:
return json.loads(r.read())
def moko_post(path, data):
payload = json.dumps(data).encode()
req = urllib.request.Request(f"{MOKO_URL}/api/v1/{path}",
data=payload, method="POST", headers={
"Authorization": f"token {MOKO_TOKEN}",
"Content-Type": "application/json",
})
with urllib.request.urlopen(req) as r:
return json.loads(r.read())
# ── Step 1: Find recently merged upstream PRs ──
since = (datetime.now(timezone.utc) - timedelta(days=DAYS)).strftime("%Y-%m-%dT%H:%M:%SZ")
query = f"repo:go-gitea/gitea is:pr is:merged base:{BRANCH} merged:>={since}"
encoded = urllib.parse.quote(query)
print(f"Scanning: {query}")
result = gh_get(f"https://api.github.com/search/issues?q={encoded}&per_page=100&sort=updated&order=desc")
total = result["total_count"]
print(f"Found {total} merged PRs in the last {DAYS} days")
if total == 0:
print("Nothing to sync.")
sys.exit(0)
# ── Step 2: Filter for bug/security fixes ──
bugs = []
for pr in result["items"]:
title = pr["title"]
label_names = [l["name"].lower() for l in pr.get("labels", [])]
is_fix = title.lower().startswith("fix")
is_security = any("security" in l for l in label_names) or "[security]" in title.lower()
is_bug = any("bug" in l for l in label_names)
if not (is_fix or is_security or is_bug):
continue
refs = re.findall(r"#(\d+)", title)
severity = "critical" if is_security and "[security]" in title.lower() else \
"high" if is_security else "medium"
bugs.append({
"number": pr["number"], "title": title, "url": pr["html_url"],
"severity": severity, "is_security": is_security, "refs": refs,
"merged": pr.get("pull_request", {}).get("merged_at", "")[:10],
})
print(f"Filtered to {len(bugs)} bug/security fixes")
if not bugs:
sys.exit(0)
# ── Step 3: Collect already-tracked PR numbers ──
tracked = set()
for state in ["open", "closed"]:
try:
issues = moko_get(f"repos/{MOKO_REPO}/issues?state={state}&type=issues&limit=50&labels=upstream")
for iss in issues:
text = (iss.get("body") or "") + " " + (iss.get("title") or "")
tracked.update(re.findall(r"(?:#|/pull/)(\d{4,})", text))
except Exception:
pass
print(f"Already tracked: {len(tracked)} upstream PRs")
# ── Step 4: Create issues for new bugs ──
created = skipped = errors = 0
for bug in bugs:
if any(r in tracked for r in bug["refs"]):
print(f" SKIP #{bug['number']}: {bug['title'][:55]} (tracked)")
skipped += 1
continue
labels = [LABELS["type_bug"], LABELS["upstream"], LABELS[bug["severity"]]]
if bug["is_security"]:
labels.append(LABELS["security"])
body = (
f"## Summary\n\n"
f"Upstream bug fix merged into `{BRANCH}`.\n\n"
f"## Upstream Reference\n\n"
f"- PR: {bug['url']}\n"
f"- Merged: {bug['merged']}\n"
f"- Branch: {BRANCH}\n\n"
f"## Severity: {bug['severity'].title()}"
f"{' (security)' if bug['is_security'] else ''}\n\n"
f"## Action\n\n"
f"Cherry-pick from upstream `{BRANCH}` branch.\n\n"
f"---\n"
f"*Auto-created by upstream-bug-sync workflow*\n"
f"*Authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>*"
)
try:
iss = moko_post(f"repos/{MOKO_REPO}/issues", {
"title": bug["title"], "body": body, "labels": labels,
})
print(f" CREATED #{iss['number']}: {bug['title'][:55]}")
created += 1
except Exception as e:
print(f" ERROR #{bug['number']}: {e}")
errors += 1
print(f"\n=== Done: {created} created, {skipped} skipped, {errors} errors ===")
PYEOF
@@ -3,17 +3,16 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGIT.Workflow
# DEFGROUP: Gitea.Workflow
# INGROUP: mokocli.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
# PATH: /.mokogit/workflows/workflow-sync-trigger.yml
# PATH: /.mokogitea/workflows/workflow-sync-trigger.yml
# VERSION: 01.01.00
# BRIEF: Trigger workflow sync to live repos when a PR is merged to main
name: "Universal: Workflow Sync Trigger"
on:
workflow_dispatch:
pull_request:
types: [closed]
branches:
@@ -27,10 +26,8 @@ jobs:
name: Sync workflows to live repos
runs-on: ubuntu-latest
if: >-
startsWith(github.event.repository.name, 'Template-') &&
(github.event_name == 'workflow_dispatch' ||
(github.event.pull_request.merged == true &&
!contains(github.event.pull_request.title, '[skip sync]')))
github.event.pull_request.merged == true &&
!contains(github.event.pull_request.title, '[skip sync]')
steps:
- name: Determine platform from repo name
@@ -41,7 +38,7 @@ jobs:
Template-Joomla) PLATFORM="joomla" ;;
Template-Dolibarr) PLATFORM="dolibarr" ;;
Template-Go) PLATFORM="go" ;;
Template-NPM) PLATFORM="npm" ;;
Template-MCP) PLATFORM="mcp" ;;
Template-Generic) PLATFORM="" ;;
*) PLATFORM="" ;;
esac
@@ -50,16 +47,10 @@ jobs:
- name: Clone mokocli
env:
MOKOGIT_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
run: |
MOKOGIT_URL="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}"
git clone --depth 1 "${MOKOGIT_URL}/MokoConsulting/mokocli.git" /tmp/mokocli
- name: Install PHP
run: |
if ! command -v php &> /dev/null; then
apt-get update -qq && apt-get install -y -qq php-cli php-json php-curl > /dev/null 2>&1
fi
GITEA_URL="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}"
git clone --depth 1 "${GITEA_URL}/MokoConsulting/mokocli.git" /tmp/mokocli
- name: Install dependencies
run: |
@@ -68,12 +59,11 @@ jobs:
- name: Run workflow sync
env:
MOKOGIT_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
run: |
ARGS="--token ${MOKOGIT_TOKEN}"
ARGS="--token ${MOKOGITEA_TOKEN}"
ARGS="${ARGS} --org ${{ vars.GITEA_ORG || github.repository_owner }}"
ARGS="${ARGS} --phase repos"
ARGS="${ARGS} --delete-orphans"
PLATFORM="${{ steps.platform.outputs.platform }}"
if [ -n "$PLATFORM" ]; then
+1 -102
View File
@@ -2,115 +2,14 @@
## [Unreleased]
### Changed
- **Rebrand: MokoGitea → MokoGIT (complete retirement of the MokoGitea name).** Go module path `code.mokoconsulting.tech/MokoConsulting/MokoGitea``.../MokoGIT` (all imports + `go.mod`); default app name `MokoGitea``MokoGIT`; the in-repo config directory and the special org profile/wiki repo names `.mokogitea` / `.mokogitea-private``.mokogit` / `.mokogit-private`; the Actions system user `mokogitea-actions``mokogit-actions` (DB migration #369); Docker image, ntfy topic, mail tags, and remaining lowercase `mokogitea` references → `mokogit`; bundled the Moko `favicon.svg` as the app icon and PWA manifest icon. Shared `MOKOGITEA_*` CI/compose env-var and org-secret names are renamed in the coordinated server cutover (not in this repo change) to avoid breaking cross-repo CI mid-transition.
### Added
- Metadata platform options are now **admin-configurable** instead of hardcoded: a new **Admin → Metadata** page edits the allowed `platform` values (persisted to `app.ini` `[metadata] PLATFORM_OPTIONS`, default `joomla,dolibarr,go,npm,generic`), and the repo Settings → Metadata platform dropdown reads from it. Changing the taxonomy no longer needs a code change/redeploy. A repo's existing platform value stays selectable even if later removed from the list (#777)
- Org branch protection: repositories now show the inherited organization rules read-only in their Branch Protection settings, with an expandable detail (direct push, force-push, branch deletion, merge restrictions, required approvals, status checks, protected files, and whitelisted teams) — like GitHub surfaces org rulesets in a repo (#727)
- Org branch protection: org-level rules can now also protect against branch deletion (`enable_delete` + delete allowlist teams), mirroring the per-repo delete allowlist (#727)
- Org-level tag protection: protect tag patterns org-wide (e.g. `v*`) with a team allowlist, layered on top of each repo's own protected tags — a tag is controllable only if allowed at both levels (fail-closed). API at `/orgs/{org}/tag_protections`; enforced at the git push/delete hook and the release create/delete paths; shown read-only in the repo Tag settings (#727)
- Org-level push policy: one policy per org, enforced in the pre-receive hook across all its repositories — branch/tag name conventions (glob), a mandatory secret-scanning block-on-push that repos cannot disable, a max pushed-file size, and blocked file-path patterns. API at `/orgs/{org}/push_policy`. Naming is fail-closed; the content checks (blocked paths, max size) fail open on error so a policy bug can never block every push (#727)
- Org-level repository defaults: an org can force new/transferred repositories private and set default pull-request settings (allowed merge styles, default merge style, auto-delete branch after merge), applied via a notifier when a repo is created in or transferred into the org (best-effort — never blocks repo creation). API at `/orgs/{org}/repo_defaults` (#727)
- Org-level email domain policy: restrict which email domains an organization's members may have — a user can only be added to the org (via any team) if their primary email matches one of the allowed domain globs. Enforced at the single membership-add choke point (`AddTeamMember`); API at `/orgs/{org}/email_domain_policy` (#727)
- Code security scanner: pattern-based detection of SQL injection, XSS, command injection, path traversal, insecure deserialization, hardcoded credentials, and weak cryptography across Go/PHP/Python/JS/TS (#552)
- Cascade merge: auto-create PRs to downstream branches after merge with configurable rules per repo (#460)
- Issue status presets: 4 built-in templates (default, software-development, support-tickets, bug-tracking) with API + web UI (#507)
- Cross-org status migration: copy status definitions from one org to another via API (#507)
- Auto-create default teams on org creation: Developers (write), Reviewers (read), CI/CD (actions+packages) (#513)
- Branch protection delete allowlist: configurable per-user/team/deploy-key allowlist for deleting protected branches (#696)
- Workflow subdirectory discovery: workflows in subdirectories of `.mokogit/workflows/` are now auto-discovered (#693)
- API token scope `read:licensing` / `write:licensing` for licensing endpoints (#697)
- Edit API token scopes: PATCH /users/{username}/tokens/{id} API endpoint + web UI edit button (#697)
- Wiki full-text search: case-insensitive search across all wiki page titles and content (#550)
- Wiki search API: GET /wiki/search?q=term with paginated JSON results (#550)
- Metadata deploy fields: deploy_host, deploy_port, deploy_user, deploy_path, docker_image, docker_registry, container_name, health_url (#692)
- Security scanning API: REST endpoints for alerts, config, and on-demand scans (GET/PATCH /security/alerts, /security/config, POST /security/scan) (#692)
- Pre-receive hook secret blocking: push rejection when block_on_push enabled and secrets detected in commits (#692)
- Metadata API partial updates: PUT /metadata now merges only sent fields instead of replacing all
- Wiki revision diff: line-by-line diff view per commit in wiki page history (#667)
- Wiki categories: YAML frontmatter `categories:` with category index page (#668)
- Wiki template transclusion: `{{template:Name|key=val}}` with `_Template/` folder (#671)
- Wiki enhanced ToC: collapsible, inline via frontmatter, sticky sidebar (#673)
- Wiki folder ACL: `_access.yml` per-folder write protection (#674)
- Wiki print view and ZIP export of all wiki pages (#675)
- Wiki features documentation page in org wiki (standards/Wiki-Features)
- DLID licensing system: license, entitlement, activation, product_tier, audit_log tables (v359 migration)
- License CRUD with CRC32-checksummed DLID generation and format validation
- Entitlement model with tier-based rebuild and custom entitlement preservation
- Domain activation tracking with limit enforcement and auto-activate on first use
- 13 seeded product tiers from base to enterprise
- DLID-gated update XML endpoint: GET /api/v1/licensing/updates/{product}.xml
- Profile repo fallback chain: .mokogit > .profile > .github
- Metadata/manifest GET endpoint publicly accessible without auth (#676)
- Org wiki: folder-based collapsible tree sidebar, _Sidebar.md overrides (#680)
- Wiki backlinks: "What links here" page showing all pages referencing current page (#669)
- Wiki wikilinks: [[Page Name]] and [[Page|Display Text]] syntax with red links for missing pages (#666)
- Required baseline issue statuses: Open and Closed are indestructible (is_required flag) (#681)
- Issue status API response includes is_required field
- Wiki recent changes page: cross-page edit activity with pagination (#670)
- Wiki page rename with automatic redirects via YAML frontmatter (#672)
### Security
- Cherry-pick upstream v1.26.3: LFS reject unknown SSH sub-verbs to prevent auth bypass (#38015)
- Cherry-pick upstream v1.26.3: bound CODEOWNERS regex match time — ReDoS prevention (#38025)
- Cherry-pick upstream v1.26.3: require merged PR to bypass fork PR approval gate (#38041)
- Cherry-pick upstream v1.26.3: LFS require Code-unit access for cross-repo object reuse (#38050)
- Cherry-pick upstream v1.26.3: hostmatcher block reserved IP ranges — SSRF prevention (#38059)
- Cherry-pick upstream v1.26.3: bound debian ParseControlFile — DoS prevention (#38055)
- Cherry-pick upstream v1.26.3: feed token scope, migration SSRF, notification redaction (#38147)
- Cherry-pick upstream v1.26.3: OIDC ignore stale external login links to organizations (#38141)
- Cherry-pick upstream v1.26.3: 2FA timing, branch delete auth, org labels visibility, merge upstream auth (#38151)
- Cherry-pick upstream v1.26.3: allow git clone of private repos with anonymous code access (#38146)
- Cherry-pick upstream v1.26.3: hostmatcher patch incorrect private IP list (#38173)
- Cherry-pick upstream v1.26.4: do not auto-reactivate disabled users on OAuth2 callback (#38183)
- Cherry-pick upstream v1.26.4: walk git log context error handling — regression fix (#38185)
### Fixed
- Repo metadata `org` is now **derived from the org profile** (the repository owner) instead of being stored/editable, so it can never drift when an organization is renamed. The `org` column is dropped from `repo_manifest` (migration #368) and the field is derived on read via `Repository.DerivedOrgName` (owner display name, falling back to the handle) across the metadata API, the Settings → Metadata page (now read-only), and the Joomla update-server feed. The API `PUT` and MCP `metadata_update` now ignore `org` (read-only, like the already-derived `display_name`) (#771)
- Admin Branding: uploading a custom **Nav Icon** now also sets the **app icon** (`logo.png`, the PWA / web-manifest icon and navbar fallback), so a branded instance shows its own installable app icon instead of the shipped default; resetting the Nav Icon reverts both (#773)
- Fork server binary now compiles: `routers/api/v1/api.go` called `organization.HasOrgOrUserVisible`, which had been renamed to `IsOwnerVisibleToDoer`; the one missed call site broke `go build` of the entire `routers/api/v1` package (CI's Lint & Validate does not run a full build, so it went unnoticed) (#735)
- Dev deploy workflow: the build/deploy step referenced runner-side values as `\$TAG` / `\$REGISTRY_TOKEN` inside an unquoted SSH heredoc, deferring expansion to the remote shell where those names are unset — the Docker tag collapsed to an empty `mokogit:` and every dev deploy failed with `invalid reference format`. Runner values are now injected via an ssh env-prefix and the heredoc is quoted so each `$var` expands in exactly one place (#737)
- Repaired unit-test compile and `go vet` failures: `CryptoRandomInt/String/Bytes` now return two values (updated `modules/util/util_test.go`), removed a redundant `&&` condition in `issue_comment.go`, and cleaned up isolated integration-test compile errors (#736)
- Removed a stray `package-lock.json` (13.9k lines) that a `git add -A` had accidentally swept into the org-push-policy branch (#734)
- Org-level branch protection now **layers** with per-repo rules instead of being ignored whenever a repo rule exists. When both an org rule and a repo rule match a branch, the effective rule is the most-restrictive (fail-closed) combination — the org rule is a mandatory floor a repo cannot weaken: allow flags AND'd, gate/require/block flags OR'd, required approvals max'd, status checks and protected-file patterns unioned, whitelists intersected. Previously a repo rule shadowed the org rule entirely at the enforcement choke point (`GetFirstMatchProtectedBranchRule`), letting a repo opt out of org protection (#727)
- Org Teams page: list now renders — the handler wrote `ctx.Data["OrgListTeams"]` but the template reads `.Teams`, so the page showed header/nav but no teams (#720)
- Issue type: now editable after creation for users with issue write permission — the sidebar gated editing on a `FieldEditFlags` data key that was never populated (always read-only); now uses `HasIssuesOrPullsWritePermission` like the priority field (#721)
- Admin config form: radio inputs (e.g. instance landing page Mode) no longer throw "Unsupported config form value mapping", which had aborted all JS init on the admin settings page
- PR check branch policy: allow `fix/*``main` and `patch/*``main` to match documented policy (was rejecting fix/patch PRs to main)
- PR check platform detection: guard for missing `.mokogit/manifest.xml` so the Validate PR job no longer aborts under `set -e` (manifest replaced by metadata API)
- Remove dangling `mcp-mokogit-api` submodule gitlink (no `.gitmodules` entry) that broke `submodule update --init` at checkout, failing all PR build/release jobs; ignore the local clone path
- PR RC Release workflow: no-op cleanly when `updates.xml` is absent (generic repos) instead of aborting the "Determine RC version" step under `set -e`
- PR check: platform detection now queries metadata API instead of removed manifest.xml
- Cherry-pick upstream v1.26.2: handle empty pull request files view to allow reviews (#37783)
- Cherry-pick upstream v1.26.2: fix "run as root" check with snap container detection (#37622)
- Cherry-pick upstream: ack re-sent UpdateLog finalize idempotently (#37885)
- Cherry-pick upstream: reject workflow_dispatch for workflows without that trigger (#37660)
- Cherry-pick upstream: keep action run title clickable when commit subject is a URL (#37867)
- Cherry-pick upstream: exclude workflow_call from workflow trigger detection (#37894)
- API token edit: reject empty scope update requests with 400 instead of silently succeeding
- Workflow token auth: pr-check.yml pre-release dispatch was silently failing due to env var / curl reference mismatch
- Workflow tokens: standardize all GA_TOKEN/GITEA_TOKEN/GITEA_URL env vars to MOKOGITEA_TOKEN/MOKOGITEA_URL across all workflow files in 5 template repos + MokoCLI (65+ files)
- CI issue reporter: rename GITEA_TOKEN/GITEA_URL to MOKOGITEA_TOKEN/MOKOGITEA_URL in automation/ci-issue-reporter.sh
- Workflow sync trigger: add workflow_dispatch event, fix if-condition to allow manual dispatch, add PHP install step for non-PHP runners
- Deploy workflow: merge dev health check into deploy job to avoid runner status reporting failures on inter-job handoff
- Licensing API: handle DB write errors in UpdateLicense, UpdateTier, DeleteTier instead of silently discarding
- Wiki API: fix findEntryForFile URL-decode fallback for non-ASCII page names
- Metadata settings template 500 error: removed reference to deleted Version field
- Wiki recent changes: use commit.MessageTitle() instead of commit.Message()
- Wiki backlinks: proper URL encoding for subdirectory pages
- Wiki wikilinks: page existence lookup normalizes spaces and hyphens
- Issue statuses template: garbled em-dash character replaced
### Changed
- Custom workflows moved to `.mokogit/workflows/custom/`: deploy-mokogit, deploy-dev, cascade-dev, pr-rc-release, test-mokogit, upstream-bug-sync
- Issue status seed defaults: Open, In Progress, Waiting, In Review, Closed, Won't Fix
- Pre-release workflow: auto-bump skipped for non-Joomla repos (platform check)
- CI issue reporter: moved to MokoCLI (cli/ci_issue_reporter.sh), pr-check and repo-health now use ci-issue-reporter.yml reusable workflow
### Removed
- Workflows: gitleaks.yml, npm-publish.yml, notify.yml, workflow-sync-trigger.yml, composer-publish.yml, deploy-manual.yml, security-audit.yml (not applicable to Go repo)
- automation/ci-issue-reporter.sh: moved to MokoCLI as centralized CLI tool
- Profile repo fallback chain: .mokogitea > .profile > .github
## [06.19.00] --- 2026-06-20
+1 -1
View File
@@ -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:
- `.mokogit/manifest.xml` (canonical source)
- `.mokogitea/manifest.xml` (canonical source)
- Joomla XML manifests (`<version>` tag)
- `README.md`, `CHANGELOG.md` (`VERSION:` pattern)
- `package.json`, `pyproject.toml`
+3 -3
View File
@@ -21,7 +21,7 @@ RUN apk --no-cache add \
build-base \
git
WORKDIR ${GOPATH}/src/code.mokoconsulting.tech/MokoConsulting/MokoGIT
WORKDIR ${GOPATH}/src/code.mokoconsulting.tech/MokoConsulting/MokoGitea
COPY go.mod go.sum ./
RUN go mod download
# Use COPY instead of bind mount as read-only one breaks makefile state tracking
@@ -43,7 +43,7 @@ RUN chmod 755 /tmp/local/usr/bin/entrypoint \
/tmp/local/etc/s6/gitea/* \
/tmp/local/etc/s6/openssh/* \
/tmp/local/etc/s6/.s6-svscan/* \
/go/src/code.mokoconsulting.tech/MokoConsulting/MokoGIT/gitea
/go/src/code.mokoconsulting.tech/MokoConsulting/MokoGitea/gitea
FROM docker.io/library/alpine:3.23 AS gitea
@@ -75,7 +75,7 @@ RUN addgroup \
echo "git:*" | chpasswd -e
COPY --from=build-env /tmp/local /
COPY --from=build-env /go/src/code.mokoconsulting.tech/MokoConsulting/MokoGIT/gitea /app/gitea/gitea
COPY --from=build-env /go/src/code.mokoconsulting.tech/MokoConsulting/MokoGitea/gitea /app/gitea/gitea
# Disable openssh s6 service — we use external SSH (port 2222 via host).
RUN printf '#!/bin/sh\nexec sleep infinity\n' > /etc/s6/openssh/run && chmod 755 /etc/s6/openssh/run
@@ -2,7 +2,7 @@
"folders":
[
{
"name":"MokoGIT",
"name":"MokoGitea",
"path": ".",
"folder_exclude_patterns":
[
+24 -34
View File
@@ -1,53 +1,43 @@
# MokoGIT
# MokoGitea
Custom Gitea fork with enhanced wiki system, DLID licensing, issue statuses, cascade merge, security scanning, org-level governance, org metadata, CI standardization, and project board API.
Moko fork of Gitea — adding project board REST API endpoints and custom enhancements
![Language](https://img.shields.io/badge/Go-00ADD8?style=flat-square&logo=go&logoColor=white) ![License](https://img.shields.io/badge/license-GPL--3.0--or--later-green?style=flat-square)
![Language](https://img.shields.io/badge/Go-00ADD8?style=flat-square&logo=go&logoColor=white) ![License](https://img.shields.io/badge/license-GPL--3.0--or--later-green?style=flat-square) ![Wiki](https://img.shields.io/badge/wiki-MokoGitea-blue?style=flat-square)
Custom Gitea fork with Project Board API
---
## Key Features
## Pages
- **Wiki System** -- wikilinks, categories, backlinks, template transclusion, revision diffs, rename redirects, folder ACL, enhanced ToC, print view, ZIP export ([details](https://git.mokoconsulting.tech/MokoConsulting/.mokogit/wiki/standards/Wiki-Features))
- **DLID Licensing** -- license management, entitlements, domain activations, ed25519-signed downloads
- **API Token Scope Editing** -- edit token scopes via API (PATCH) or web UI after creation
- **Issue Statuses** -- custom workflow statuses per org with required baseline protection, presets, cross-org migration
- **Cascade Merge** -- auto-create PRs to downstream branches after merge with configurable rules per repo
- **Security Scanning** -- secret detection (pre-receive blocking) + code analysis (SQL injection, XSS, command injection, path traversal, and more) with REST API for alerts, config, and on-demand scans
- **Default Org Teams** -- auto-create Developers, Reviewers, and CI/CD teams on org creation
- **Org Metadata** -- per-repo metadata API (public GET, admin PUT), platform detection for versioning
- **Branch Protection** -- delete allowlist for protected branches (per-user/team/deploy-key)
- **Org Governance** -- organization-wide rules that layer onto every repository: branch protection as a most-restrictive floor a repo cannot weaken, tag protection (team allowlist), push policy (branch/tag naming, mandatory secret-block, max file size, blocked paths), repository defaults (force-private, PR merge settings), and member email-domain allowlists
- **Project Board API** -- REST endpoints for project columns and cards
- **CI Infrastructure** -- reusable workflows, centralized ci-issue-reporter, standardized MOKOGITEA_TOKEN naming
- **Dev Deploy Gate** -- builds deploy to dev environment first, production checks dev health
- [Branding](https://code.mokoconsulting.tech/MokoConsulting/MokoGitea/wiki/Branding)
- [Deployment](https://code.mokoconsulting.tech/MokoConsulting/MokoGitea/wiki/Deployment)
- [Project API](Project API)
- [roadmap](https://code.mokoconsulting.tech/MokoConsulting/MokoGitea/wiki/roadmap)
---
**Category:** Infrastructure | **Platform:** [MokoPlatform wiki](https://code.mokoconsulting.tech/MokoConsulting/MokoPlatform/wiki)
---
---
## Documentation
- [Org Wiki](https://git.mokoconsulting.tech/MokoConsulting/.mokogit/wiki/) -- standards, CLI reference, API docs
- [Wiki Features](https://git.mokoconsulting.tech/MokoConsulting/.mokogit/wiki/standards/Wiki-Features) -- all 10 wiki enhancements
- [Licensing API](https://git.mokoconsulting.tech/MokoConsulting/.mokogit/wiki/api/Licensing-API)
- [Repo Wiki](https://git.mokoconsulting.tech/MokoConsulting/MokoGIT/wiki/) -- feature docs, API reference, operations
Full documentation is available on the [Wiki](https://code.mokoconsulting.tech/MokoConsulting/MokoGitea/wiki).
## Contributing
See the [org wiki](https://git.mokoconsulting.tech/MokoConsulting/.mokogit/wiki/) for development guidelines, coding standards, and contribution instructions.
See the wiki for development guidelines and contribution instructions.
## License
This project is licensed under the GNU General Public License v3.0 or later -- see the [LICENSE](LICENSE) file.
## Third-Party & Vendored Assets
MokoGIT bundles third-party assets under their own licenses. Full attribution and
license texts are in [THIRD-PARTY-NOTICES.md](THIRD-PARTY-NOTICES.md) and travel with
every distribution and white-labeled build.
- **[Font Awesome Free 7.1.0](https://fontawesome.com)** -- (c) 2025 Fonticons, Inc.
Icons under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), fonts under
[SIL OFL 1.1](https://scripts.sil.org/OFL), code under [MIT](https://opensource.org/licenses/MIT).
Vendored unmodified at `web_src/css/vendor/fontawesome/` (see its `LICENSE.txt`).
---
*[Moko Consulting](https://mokoconsulting.tech)*
*[Moko Consulting](https://mokoconsulting.tech) -- [MokoStandards](https://code.mokoconsulting.tech/MokoConsulting/MokoPlatform/wiki/Home)*
-40
View File
@@ -1,40 +0,0 @@
<!--
SPDX-License-Identifier: MIT
This file lists third-party assets vendored into MokoGIT and the attribution
required by their licenses. It is intended to travel with every distribution and
white-labeled build. Do not remove third-party attribution when rebranding.
-->
# Third-Party Notices
MokoGIT bundles the third-party assets listed below. Each is redistributed under
its own license; the required attribution and license texts are retained here and
alongside the vendored files. Rebranding / white-labeling MokoGIT does **not**
remove these obligations — this file (and the referenced license files) must be
distributed with the product.
## Font Awesome Free 7.1.0
- **Project:** Font Awesome Free
- **Version:** 7.1.0
- **Author / Copyright:** © 2025 Fonticons, Inc. — https://fontawesome.com
- **Homepage / License:** https://fontawesome.com/license/free
- **Vendored at:** `web_src/css/vendor/fontawesome/` (CSS + webfonts, unmodified)
- **Full license text:** `web_src/css/vendor/fontawesome/LICENSE.txt`
Font Awesome Free is multi-licensed by file type:
| Component | License | Notes |
| --- | --- | --- |
| Icons (SVG/JS glyph designs) | **CC BY 4.0** (https://creativecommons.org/licenses/by/4.0/) | Attribution to Fonticons, Inc. required. Satisfied by this notice + the retained CSS header. |
| Fonts (`.woff2` webfonts) | **SIL OFL 1.1** (https://scripts.sil.org/OFL) | Distributed with the OFL text (in `LICENSE.txt`). Font files are shipped **unmodified**; the reserved font name "Font Awesome" is retained. |
| Code (CSS) | **MIT** (https://opensource.org/licenses/MIT) | Copyright header retained in `all.min.css`. |
**Compliance notes for distribution / white-labeling:**
- The vendored `.woff2` font files are byte-for-byte unmodified. Do not subset,
re-generate, or rename them — doing so triggers the SIL OFL Reserved Font Name
restriction.
- The license header comment in `all.min.css` must be preserved.
- Attribution may live in this notices file and the licenses page rather than in
the visible (white-labeled) UI; it must remain accessible to end users.
-1
View File
@@ -1 +0,0 @@
01.00.00
-42
View File
@@ -1,42 +0,0 @@
<!-- SPDX-License-Identifier: GPL-3.0-or-later -->
# MokoGIT Versioning
MokoGIT follows the **MokoOrgStandards `xx.xx.xx`** scheme: `MAJOR.MINOR.PATCH`, **two digits
per segment** (e.g. `01.00.00`, `01.04.12`). This is MokoGIT's own version line — it deliberately
**replaces the inherited upstream Gitea version** (which previously leaked through as
`1.24.0+dev-<N>-g<hash>`).
## Where the version comes from
The binary version is injected at build time into `main.Version``setting.AppVer` (drives the
footer, `/api/v1/version`, and the PWA manifest). The Makefile resolves it in this order:
| Build type | Source | Result |
| --- | --- | --- |
| **Release (git tag)** | the tag name (`$GITHUB_REF_NAME`, `v` stripped) | e.g. tag `01.00.00``01.00.00` |
| **Branch / dev** | the repo-root **`VERSION`** file (`STORED_VERSION`) | `01.00.00` |
| _(fallback only if `VERSION` is absent)_ | `git describe --tags` | would leak the Gitea base — avoided by shipping `VERSION` |
The committed `VERSION` file (currently `01.00.00`) is what strips the Gitea base on ordinary
branch builds. **Do not delete it.**
## Release tagging — MUST use `xx.xx.xx`
Release/tag automation MUST create tags in the `xx.xx.xx` form (e.g. `01.00.00`). Because the
deploy workflows derive the container image tag from `git describe --tags`, tagging with
`01.00.00` makes the deployed image report MokoGIT's version rather than Gitea's. Tiers append a
suffix: dev → `-dev`, rc → `-rc`.
## Update checker
The upstream update-checker defaults to **disabled** (`modules/setting/setting.go`) — a fork must
not compare its `AppVer` against Gitea's release feed. Re-enable only against a MokoGIT endpoint.
## Scope of a bump
- **PATCH** — fixes, no behavior change.
- **MINOR** — backward-compatible features (default bump for feature/dev → stable releases).
- **MAJOR** — breaking changes.
Per-stack and per-tier `VERSION` files also live under `deploy/git/` for the `.vault` git stack.
+237
View File
@@ -0,0 +1,237 @@
#!/usr/bin/env bash
# ============================================================================
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Automation.CI
# INGROUP: moko-platform.Automation
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
# PATH: /automation/ci-issue-reporter.sh
# VERSION: 09.23.00
# BRIEF: Creates or updates a Gitea 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.
# ============================================================================
set -euo pipefail
# ── Defaults ────────────────────────────────────────────────────────────────
GITEA_URL="${GITEA_URL:-https://git.mokoconsulting.tech}"
GITEA_TOKEN="${GITEA_TOKEN:-}"
REPO="${GITHUB_REPOSITORY:-}"
RUN_URL="${GITHUB_SERVER_URL:-${GITEA_URL}}/${REPO}/actions/runs/${GITHUB_RUN_ID:-0}"
LABEL_NAME="ci-auto"
LABEL_COLOR="#e11d48"
GATE=""
DETAILS=""
SEVERITY="error"
WORKFLOW=""
# ── Parse arguments ─────────────────────────────────────────────────────────
usage() {
cat <<EOF
Usage: ci-issue-reporter.sh --gate NAME --details TEXT [OPTIONS]
Required:
--gate CI gate name (e.g. "Code Quality", "Self-Health")
--details Human-readable failure description
Optional:
--severity "error" (default) or "warning"
--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: \$GITEA_TOKEN)
--url Gitea base URL (default: \$GITEA_URL)
EOF
exit 1
}
while [[ $# -gt 0 ]]; do
case "$1" in
--gate) GATE="$2"; shift 2 ;;
--details) DETAILS="$2"; shift 2 ;;
--severity) SEVERITY="$2"; shift 2 ;;
--workflow) WORKFLOW="$2"; shift 2 ;;
--repo) REPO="$2"; shift 2 ;;
--run-url) RUN_URL="$2"; shift 2 ;;
--token) GITEA_TOKEN="$2"; shift 2 ;;
--url) GITEA_URL="$2"; shift 2 ;;
-h|--help) usage ;;
*) echo "Unknown option: $1"; usage ;;
esac
done
[[ -z "$GATE" ]] && { echo "ERROR: --gate is required"; usage; }
[[ -z "$DETAILS" ]] && { echo "ERROR: --details is required"; usage; }
[[ -z "$GITEA_TOKEN" ]] && { echo "ERROR: GITEA_TOKEN not set"; exit 1; }
[[ -z "$REPO" ]] && { echo "ERROR: GITHUB_REPOSITORY not set"; exit 1; }
API="${GITEA_URL}/api/v1/repos/${REPO}"
# ── Build title ─────────────────────────────────────────────────────────────
if [[ -n "$WORKFLOW" ]]; then
TITLE="[CI] ${WORKFLOW}: ${GATE} failed"
else
TITLE="[CI] ${GATE} failed"
fi
# ── Ensure label exists ─────────────────────────────────────────────────────
ensure_label() {
local exists
exists=$(curl -sf -o /dev/null -w '%{http_code}' \
-H "Authorization: token ${GITEA_TOKEN}" \
"${API}/labels" 2>/dev/null || echo "000")
if [[ "$exists" == "200" ]]; then
# Check if label already exists
local found
found=$(curl -sf \
-H "Authorization: token ${GITEA_TOKEN}" \
"${API}/labels" 2>/dev/null \
| grep -o "\"name\":\"${LABEL_NAME}\"" || true)
if [[ -z "$found" ]]; then
curl -sf -X POST \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"${API}/labels" \
-d "{\"name\":\"${LABEL_NAME}\",\"color\":\"${LABEL_COLOR}\",\"description\":\"Auto-created by CI issue reporter\"}" \
> /dev/null 2>&1 || true
fi
fi
}
# ── Search for existing open issue ──────────────────────────────────────────
find_existing_issue() {
# URL-encode the gate name for the query
local query
query=$(printf '%s' "[CI] ${GATE}" | sed 's/ /%20/g; s/\[/%5B/g; s/\]/%5D/g')
local response
response=$(curl -sf \
-H "Authorization: token ${GITEA_TOKEN}" \
"${API}/issues?type=issues&state=open&labels=${LABEL_NAME}&q=${query}&limit=5" \
2>/dev/null || echo "[]")
# Extract the first matching issue number
echo "$response" \
| grep -oP '"number":\s*\K[0-9]+' \
| head -1
}
# ── Build issue body ────────────────────────────────────────────────────────
build_body() {
local severity_badge
if [[ "$SEVERITY" == "error" ]]; then
severity_badge="**Severity:** Error"
else
severity_badge="**Severity:** Warning"
fi
cat <<BODY
## CI Gate Failure: ${GATE}
${severity_badge}
**Workflow:** ${WORKFLOW:-unknown}
**Branch:** ${GITHUB_REF_NAME:-unknown}
**Commit:** \`${GITHUB_SHA:0:8}\`
**Run:** [View CI run](${RUN_URL})
### Details
${DETAILS}
### Resolution
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](${GITEA_URL}/${REPO}/src/branch/main/automation/ci-issue-reporter.sh)*
BODY
}
# ── Build comment body (for existing issues) ────────────────────────────────
build_comment() {
cat <<COMMENT
### CI failure recurrence
**Branch:** ${GITHUB_REF_NAME:-unknown}
**Commit:** \`${GITHUB_SHA:0:8}\`
**Run:** [View CI run](${RUN_URL})
${DETAILS}
COMMENT
}
# ── Main ────────────────────────────────────────────────────────────────────
ensure_label
EXISTING=$(find_existing_issue)
if [[ -n "$EXISTING" ]]; then
# Append comment to existing issue
COMMENT_BODY=$(build_comment)
COMMENT_JSON=$(printf '%s' "$COMMENT_BODY" | python3 -c "
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 ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"${API}/issues/${EXISTING}/comments" \
-d "${COMMENT_JSON}" 2>/dev/null || echo "000")
if [[ "$HTTP" == "201" ]]; then
echo "Commented on existing issue #${EXISTING}"
else
echo "WARNING: Failed to comment on issue #${EXISTING} (HTTP ${HTTP})"
fi
else
# Create new issue
ISSUE_BODY=$(build_body)
ISSUE_JSON=$(python3 -c "
import sys, json
body = sys.stdin.read()
print(json.dumps({
'title': sys.argv[1],
'body': body,
'labels': []
}))" "$TITLE" <<< "$ISSUE_BODY" 2>/dev/null)
# Create the issue
RESPONSE=$(curl -sf -X POST \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"${API}/issues" \
-d "${ISSUE_JSON}" 2>/dev/null || echo "{}")
ISSUE_NUM=$(echo "$RESPONSE" | grep -oP '"number":\s*\K[0-9]+' | head -1)
if [[ -n "$ISSUE_NUM" ]]; then
# Apply label (separate call — more reliable across Gitea versions)
LABEL_ID=$(curl -sf \
-H "Authorization: token ${GITEA_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 ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"${API}/issues/${ISSUE_NUM}/labels" \
-d "{\"labels\":[${LABEL_ID}]}" \
> /dev/null 2>&1 || true
fi
echo "Created issue #${ISSUE_NUM}: ${TITLE}"
else
echo "WARNING: Failed to create issue"
echo "Response: ${RESPONSE}"
fi
fi
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"fmt"
"os"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/assetfs"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/assetfs"
)
func main() {
+1 -1
View File
@@ -20,7 +20,7 @@ import (
"strings"
"unicode/utf8"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/json"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/json"
)
const (
+1 -1
View File
@@ -15,7 +15,7 @@ import (
"path/filepath"
"strings"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
)
func main() {
+1 -1
View File
@@ -30,7 +30,7 @@ var primaryLicenseRe = regexp.MustCompile(`^(?i)(LICEN[SC]E|COPYING)$`)
// ignoredNames are LicenseEntry.Name values to exclude from the output.
var ignoredNames = map[string]bool{
"code.gitea.io/gitea": true,
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/options/license": true,
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/options/license": true,
}
var excludedExt = map[string]bool{
+1 -1
View File
@@ -25,7 +25,7 @@ import (
"sort"
"strings"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/build/openapi3gen"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/build/openapi3gen"
"github.com/getkin/kin-openapi/openapi3"
)
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"regexp"
"strings"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/json"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/json"
"github.com/getkin/kin-openapi/openapi2"
"github.com/getkin/kin-openapi/openapi2conv"
+2 -2
View File
@@ -7,8 +7,8 @@ import (
"context"
"fmt"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/private"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/private"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"github.com/urfave/cli/v3"
)
+6 -6
View File
@@ -8,12 +8,12 @@ import (
"context"
"fmt"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/db"
repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/repo"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/git"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/gitrepo"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/log"
repo_module "code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/repository"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/git"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/gitrepo"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
repo_module "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/repository"
"github.com/urfave/cli/v3"
)
+3 -3
View File
@@ -10,9 +10,9 @@ import (
"os"
"text/tabwriter"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/db"
auth_service "code.mokoconsulting.tech/MokoConsulting/MokoGIT/services/auth"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
auth_service "code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/auth"
"github.com/urfave/cli/v3"
)
+3 -3
View File
@@ -8,9 +8,9 @@ import (
"fmt"
"strings"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/services/auth/source/ldap"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/auth/source/ldap"
"github.com/urfave/cli/v3"
)
+3 -3
View File
@@ -7,9 +7,9 @@ import (
"context"
"testing"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/test"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/services/auth/source/ldap"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/test"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/auth/source/ldap"
"github.com/stretchr/testify/assert"
"github.com/urfave/cli/v3"
+3 -3
View File
@@ -9,9 +9,9 @@ import (
"fmt"
"net/url"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/services/auth/source/oauth2"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/auth/source/oauth2"
"github.com/urfave/cli/v3"
)
+2 -2
View File
@@ -7,8 +7,8 @@ import (
"context"
"testing"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/services/auth/source/oauth2"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/auth/source/oauth2"
"github.com/stretchr/testify/assert"
"github.com/urfave/cli/v3"
+3 -3
View File
@@ -8,9 +8,9 @@ import (
"errors"
"strings"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/services/auth/source/smtp"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/auth/source/smtp"
"github.com/urfave/cli/v3"
)
+2 -2
View File
@@ -7,8 +7,8 @@ import (
"context"
"testing"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/services/auth/source/smtp"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/auth/source/smtp"
"github.com/stretchr/testify/assert"
"github.com/urfave/cli/v3"
+3 -3
View File
@@ -6,9 +6,9 @@ package cmd
import (
"context"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/graceful"
asymkey_service "code.mokoconsulting.tech/MokoConsulting/MokoGIT/services/asymkey"
repo_service "code.mokoconsulting.tech/MokoConsulting/MokoGIT/services/repository"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/graceful"
asymkey_service "code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/asymkey"
repo_service "code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/repository"
"github.com/urfave/cli/v3"
)
+5 -5
View File
@@ -8,11 +8,11 @@ import (
"errors"
"fmt"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/auth/password"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/optional"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/setting"
user_service "code.mokoconsulting.tech/MokoConsulting/MokoGIT/services/user"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/auth/password"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/optional"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
user_service "code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/user"
"github.com/urfave/cli/v3"
)
+3 -3
View File
@@ -7,9 +7,9 @@ import (
"io"
"testing"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/unittest"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+6 -6
View File
@@ -9,12 +9,12 @@ import (
"fmt"
"strings"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/db"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/user"
pwd "code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/auth/password"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/optional"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/setting"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
pwd "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/auth/password"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/optional"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"github.com/urfave/cli/v3"
)
+4 -4
View File
@@ -8,10 +8,10 @@ import (
"strings"
"testing"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/unittest"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/user"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+4 -4
View File
@@ -9,10 +9,10 @@ import (
"fmt"
"strings"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/storage"
user_service "code.mokoconsulting.tech/MokoConsulting/MokoGIT/services/user"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/storage"
user_service "code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/user"
"github.com/urfave/cli/v3"
)
+4 -4
View File
@@ -8,10 +8,10 @@ import (
"strings"
"testing"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/unittest"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/user"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"github.com/stretchr/testify/require"
)
+2 -2
View File
@@ -8,8 +8,8 @@ import (
"errors"
"fmt"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/auth"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/user"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"github.com/urfave/cli/v3"
)
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"os"
"text/tabwriter"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/user"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"github.com/urfave/cli/v3"
)
+2 -2
View File
@@ -8,8 +8,8 @@ import (
"errors"
"fmt"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/setting"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"github.com/urfave/cli/v3"
)
+3 -3
View File
@@ -6,9 +6,9 @@ package cmd
import (
"testing"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/unittest"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+5 -5
View File
@@ -15,11 +15,11 @@ import (
"strings"
"testing"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/cmd"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/unittest"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/test"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/cmd"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/test"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"github.com/stretchr/testify/assert"
"github.com/urfave/cli/v3"
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"fmt"
"os"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"github.com/urfave/cli/v3"
)
+7 -7
View File
@@ -12,13 +12,13 @@ import (
"strings"
"text/tabwriter"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/migrations"
migrate_base "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/migrations/base"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/container"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/services/doctor"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/migrations"
migrate_base "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/migrations/base"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/container"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/doctor"
"github.com/urfave/cli/v3"
"xorm.io/xorm"
+3 -3
View File
@@ -7,9 +7,9 @@ import (
"context"
"fmt"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"github.com/urfave/cli/v3"
)
+2 -2
View File
@@ -7,8 +7,8 @@ import (
"context"
"testing"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/services/doctor"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/doctor"
"github.com/stretchr/testify/assert"
"github.com/urfave/cli/v3"
+7 -7
View File
@@ -11,13 +11,13 @@ import (
"path/filepath"
"strings"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/dump"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/json"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/storage"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/dump"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/json"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/storage"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"gitea.com/go-chi/session"
"github.com/urfave/cli/v3"
+8 -8
View File
@@ -10,14 +10,14 @@ import (
"os"
"strings"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/git"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/log"
base "code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/migration"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/structs"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/services/convert"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/services/migrations"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/git"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
base "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/migration"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/structs"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/convert"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/migrations"
"github.com/urfave/cli/v3"
)
+8 -8
View File
@@ -11,14 +11,14 @@ import (
"path/filepath"
"strings"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/assetfs"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/glob"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/options"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/public"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/templates"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/assetfs"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/glob"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/options"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/public"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/templates"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"github.com/urfave/cli/v3"
)
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"fmt"
"os"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/generate"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/generate"
"github.com/mattn/go-isatty"
"github.com/urfave/cli/v3"
+3 -3
View File
@@ -15,9 +15,9 @@ import (
"strings"
"syscall"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"github.com/urfave/cli/v3"
)
+6 -6
View File
@@ -14,12 +14,12 @@ import (
"strings"
"time"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/git"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/git/gitcmd"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/private"
repo_module "code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/repository"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/git"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/git/gitcmd"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/private"
repo_module "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/repository"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"github.com/urfave/cli/v3"
)
+2 -2
View File
@@ -9,8 +9,8 @@ import (
"fmt"
"strings"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/private"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/private"
"github.com/urfave/cli/v3"
)
+2 -2
View File
@@ -7,8 +7,8 @@ import (
"context"
"fmt"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/private"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/private"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"github.com/urfave/cli/v3"
)
+2 -2
View File
@@ -10,8 +10,8 @@ import (
"os"
"strings"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"github.com/urfave/cli/v3"
)
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"context"
"testing"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/unittest"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
"github.com/stretchr/testify/assert"
"github.com/urfave/cli/v3"
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"os"
"time"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/private"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/private"
"github.com/urfave/cli/v3"
)
+2 -2
View File
@@ -9,8 +9,8 @@ import (
"fmt"
"os"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/private"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/private"
"github.com/urfave/cli/v3"
)
+4 -4
View File
@@ -6,10 +6,10 @@ package cmd
import (
"context"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/services/versioned_migration"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/versioned_migration"
"github.com/urfave/cli/v3"
)
+11 -11
View File
@@ -10,17 +10,17 @@ import (
"io/fs"
"strings"
actions_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/actions"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/db"
git_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/git"
packages_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/packages"
repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/repo"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/log"
packages_module "code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/packages"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/storage"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/services/versioned_migration"
actions_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/actions"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
git_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/git"
packages_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/packages"
repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
packages_module "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/packages"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/storage"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/versioned_migration"
"github.com/urfave/cli/v3"
)
+7 -7
View File
@@ -8,13 +8,13 @@ import (
"strings"
"testing"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/packages"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/unittest"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/user"
packages_module "code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/packages"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/storage"
packages_service "code.mokoconsulting.tech/MokoConsulting/MokoGIT/services/packages"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/packages"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
packages_module "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/packages"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/storage"
packages_service "code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/packages"
"github.com/stretchr/testify/assert"
)

Some files were not shown because too many files have changed in this diff Show More