release: manifest sync + element name + workflow rename #574
@@ -39,4 +39,4 @@ GITEA_TEST_E2E_FLAGS='<filepath>' make test-e2e # Single Playwright test
|
||||
- Add `Co-Authored-By` lines to all commits
|
||||
- **Workflow directory**: `.mokogitea/` (not `.gitea/` or `.github/`)
|
||||
- **Attribution**: `Authored-by: Moko Consulting`
|
||||
- **Standards**: [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)
|
||||
- **Standards**: [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home)
|
||||
|
||||
@@ -8,7 +8,7 @@ contact_links:
|
||||
url: https://mokoconsulting.tech/
|
||||
about: Get help or ask questions through our website
|
||||
- name: 📚 MokoStandards Documentation
|
||||
url: https://code.mokoconsulting.tech/MokoConsulting/moko-platform
|
||||
url: https://code.mokoconsulting.tech/MokoConsulting/mokoplatform
|
||||
about: View our coding standards and best practices
|
||||
- name: 🔒 Report a Security Vulnerability
|
||||
url: https://code.mokoconsulting.tech/mokoconsulting-tech/.github-private/security/advisories/new
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: moko-platform.Automation
|
||||
# REPO: https://code.mokoconsulting.tech/MokoConsulting/moko-platform
|
||||
# INGROUP: mokoplatform.Automation
|
||||
# REPO: https://code.mokoconsulting.tech/MokoConsulting/mokoplatform
|
||||
# PATH: /.gitea/workflows/branch-protection.yml
|
||||
# BRIEF: Apply standardised branch protection rules to all governed repositories
|
||||
#
|
||||
@@ -62,7 +62,7 @@ jobs:
|
||||
API="${GITEA_URL}/api/v1"
|
||||
|
||||
# Platform/standards/infra repos to exclude
|
||||
EXCLUDE="gitea-org-config org-profile gitea-private .mokogitea-private MokoStandards moko-platform 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
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<moko-platform xmlns="https://standards.mokoconsulting.tech/moko-platform/1.0" schema-version="1.0">
|
||||
<mokoplatform xmlns="https://standards.mokoconsulting.tech/mokoplatform/1.0" schema-version="1.0">
|
||||
<identity>
|
||||
<name>MokoGitea</name>
|
||||
<org>MokoConsulting</org>
|
||||
<description>Moko fork of Gitea — adding project board REST API endpoints and custom enhancements</description>
|
||||
<version>05.51.01</version>
|
||||
<description>Moko fork of Gitea - adding project board REST API endpoints and custom enhancements</description>
|
||||
<version>06.12.00</version>
|
||||
<version-prefix>v1.26.1+MOKO</version-prefix>
|
||||
<license spdx="GPL-3.0-or-later">GNU General Public License v3</license>
|
||||
</identity>
|
||||
<governance>
|
||||
<platform>go</platform>
|
||||
<standards-version>05.00.00</standards-version>
|
||||
<standards-source>https://code.mokoconsulting.tech/MokoConsulting/moko-platform</standards-source>
|
||||
<standards-source>https://code.mokoconsulting.tech/MokoConsulting/mokoplatform</standards-source>
|
||||
</governance>
|
||||
<build>
|
||||
<language>Go</language>
|
||||
<package-type>application</package-type>
|
||||
<entry-point>./</entry-point>
|
||||
</build>
|
||||
</moko-platform>
|
||||
</mokoplatform>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: MokoStandards.Universal
|
||||
# REPO: https://code.mokoconsulting.tech/MokoConsulting/moko-platform
|
||||
# REPO: https://code.mokoconsulting.tech/MokoConsulting/mokoplatform
|
||||
# PATH: /.mokogitea/workflows/branch-cleanup.yml
|
||||
# VERSION: 01.00.00
|
||||
# BRIEF: Delete feature branches after PR merge
|
||||
|
||||
@@ -11,7 +11,7 @@ on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Version tag (e.g. v1.26.1-moko.05.01.00)'
|
||||
description: 'Version tag (e.g. v1.26.1+MOKO06.12.00)'
|
||||
required: true
|
||||
default: 'latest'
|
||||
environment:
|
||||
@@ -180,10 +180,21 @@ jobs:
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Extract moko version from tag (e.g. v1.26.1-moko.05.01.01 -> 05.01.01)
|
||||
MOKO_VER=$(echo "$TAG" | sed -n 's/.*-moko\.\(.*\)/\1/p')
|
||||
# Extract project version by stripping the version prefix from the tag.
|
||||
# Reads prefix from manifest API (e.g. "v1.26.1+MOKO"), falls back to legacy pattern.
|
||||
API_BASE="https://${REGISTRY}/api/v1/repos/MokoConsulting/MokoGitea"
|
||||
PREFIX=$(curl -sf -H "Authorization: token ${GITEA_TOKEN}" \
|
||||
"${API_BASE}/manifest" | python3 -c "import json,sys; print(json.load(sys.stdin).get('version_prefix',''))" 2>/dev/null || true)
|
||||
|
||||
if [ -n "$PREFIX" ]; then
|
||||
MOKO_VER="${TAG#$PREFIX}"
|
||||
else
|
||||
# Legacy fallback: strip everything up to and including "-moko."
|
||||
MOKO_VER=$(echo "$TAG" | sed -n 's/.*-moko\.\(.*\)/\1/p')
|
||||
fi
|
||||
|
||||
if [ -z "$MOKO_VER" ]; then
|
||||
echo "Could not extract moko version from tag: $TAG"
|
||||
echo "Could not extract version from tag: $TAG (prefix: ${PREFIX:-none})"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: moko-platform.Automation
|
||||
# VERSION: 05.51.01
|
||||
# INGROUP: mokoplatform.Automation
|
||||
# VERSION: 06.12.00
|
||||
# BRIEF: Auto-create feature branch when an issue is opened
|
||||
|
||||
name: "Universal: Issue Branch"
|
||||
|
||||
+508
-508
File diff suppressed because it is too large
Load Diff
@@ -4,8 +4,8 @@
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: moko-platform.Release
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
|
||||
# INGROUP: mokoplatform.Release
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform
|
||||
# PATH: /templates/workflows/universal/pre-release.yml.template
|
||||
# VERSION: 05.01.00
|
||||
# BRIEF: Auto pre-release on push to dev/alpha/beta/rc branches
|
||||
@@ -55,25 +55,25 @@ jobs:
|
||||
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
ref: ${{ github.ref_name }}
|
||||
|
||||
- name: Setup moko-platform tools
|
||||
- name: Setup mokoplatform tools
|
||||
env:
|
||||
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
||||
run: |
|
||||
# Use pre-installed /opt/moko-platform if available (updated by cron every 6h)
|
||||
if [ -f /opt/moko-platform/cli/version_bump.php ] && [ -f /opt/moko-platform/cli/manifest_element.php ] && [ -f /opt/moko-platform/vendor/autoload.php ]; then
|
||||
echo Using pre-installed /opt/moko-platform
|
||||
echo MOKO_CLI=/opt/moko-platform/cli >> $GITHUB_ENV
|
||||
# Use pre-installed /opt/mokoplatform if available (updated by cron every 6h)
|
||||
if [ -f /opt/mokoplatform/cli/version_bump.php ] && [ -f /opt/mokoplatform/cli/manifest_element.php ] && [ -f /opt/mokoplatform/vendor/autoload.php ]; then
|
||||
echo Using pre-installed /opt/mokoplatform
|
||||
echo MOKO_CLI=/opt/mokoplatform/cli >> $GITHUB_ENV
|
||||
else
|
||||
echo Falling back to fresh clone
|
||||
if ! command -v composer > /dev/null 2>&1; then
|
||||
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1
|
||||
fi
|
||||
rm -rf /tmp/moko-platform-api
|
||||
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git
|
||||
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/moko-platform-api
|
||||
cd /tmp/moko-platform-api && composer install --no-dev --no-interaction --quiet
|
||||
echo MOKO_CLI=/tmp/moko-platform-api/cli >> $GITHUB_ENV
|
||||
rm -rf /tmp/mokoplatform-api
|
||||
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokoplatform.git
|
||||
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokoplatform-api
|
||||
cd /tmp/mokoplatform-api && composer install --no-dev --no-interaction --quiet
|
||||
echo MOKO_CLI=/tmp/mokoplatform-api/cli >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Detect platform
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: MokoPlatform.Universal
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform
|
||||
# PATH: /.mokogitea/workflows/rc-revert.yml
|
||||
# VERSION: 09.23.00
|
||||
# BRIEF: Rename rc/ branch back to dev/ when PR is closed without merge
|
||||
|
||||
name: "RC Revert"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
revert:
|
||||
name: Rename rc/ back to dev/
|
||||
runs-on: ubuntu-latest
|
||||
if: >-
|
||||
github.event.pull_request.merged == false &&
|
||||
startsWith(github.event.pull_request.head.ref, 'rc/')
|
||||
|
||||
steps:
|
||||
- name: Rename branch
|
||||
run: |
|
||||
BRANCH="${{ github.event.pull_request.head.ref }}"
|
||||
SUFFIX="${BRANCH#rc/}"
|
||||
DEV_BRANCH="dev/${SUFFIX}"
|
||||
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 \
|
||||
-H "Authorization: token ${TOKEN}" \
|
||||
-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
|
||||
else
|
||||
echo "::error::Failed to create ${DEV_BRANCH} from ${BRANCH} (HTTP ${STATUS})"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 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
|
||||
else
|
||||
echo "::warning::Failed to delete ${BRANCH} (HTTP ${STATUS})"
|
||||
fi
|
||||
|
||||
echo "### RC Reverted" >> $GITHUB_STEP_SUMMARY
|
||||
echo "${BRANCH} → ${DEV_BRANCH}" >> $GITHUB_STEP_SUMMARY
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,134 @@
|
||||
// Copyright 2026 The MokoGitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ai
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
|
||||
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
|
||||
)
|
||||
|
||||
// OrgSetting stores AI configuration for an organization.
|
||||
type OrgSetting struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
OrgID int64 `xorm:"UNIQUE NOT NULL"`
|
||||
Enabled bool `xorm:"NOT NULL DEFAULT true"`
|
||||
APIKeyEncrypted string `xorm:"TEXT"`
|
||||
Model string `xorm:"VARCHAR(50) NOT NULL DEFAULT 'claude-sonnet-4-6'"`
|
||||
RateLimitRequests int `xorm:"NOT NULL DEFAULT 100"`
|
||||
RateLimitTokensMonth int64 `xorm:"NOT NULL DEFAULT 5000000"`
|
||||
CreatedUnix timeutil.TimeStamp
|
||||
UpdatedUnix timeutil.TimeStamp
|
||||
}
|
||||
|
||||
func init() {
|
||||
db.RegisterModel(new(OrgSetting))
|
||||
db.RegisterModel(new(RepoSetting))
|
||||
db.RegisterModel(new(UsageLog))
|
||||
}
|
||||
|
||||
// TableName returns the table name for OrgSetting.
|
||||
func (OrgSetting) TableName() string {
|
||||
return "ai_org_setting"
|
||||
}
|
||||
|
||||
// RepoSetting stores AI configuration for a repository.
|
||||
type RepoSetting struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
RepoID int64 `xorm:"UNIQUE NOT NULL"`
|
||||
Enabled bool `xorm:"NOT NULL DEFAULT true"`
|
||||
AutoReview bool `xorm:"NOT NULL DEFAULT true"`
|
||||
Strictness string `xorm:"VARCHAR(20) NOT NULL DEFAULT 'standard'"`
|
||||
IgnorePatterns string `xorm:"TEXT"`
|
||||
CreatedUnix timeutil.TimeStamp
|
||||
UpdatedUnix timeutil.TimeStamp
|
||||
}
|
||||
|
||||
// TableName returns the table name for RepoSetting.
|
||||
func (RepoSetting) TableName() string {
|
||||
return "ai_repo_setting"
|
||||
}
|
||||
|
||||
// UsageLog records AI token usage per action.
|
||||
type UsageLog struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
OrgID int64 `xorm:"INDEX NOT NULL"`
|
||||
RepoID int64 `xorm:"INDEX NOT NULL"`
|
||||
TriggeredByID int64
|
||||
ActionType string `xorm:"VARCHAR(20) NOT NULL"` // review, chat, agent
|
||||
Model string `xorm:"VARCHAR(50)"`
|
||||
TokensInput int64
|
||||
TokensOutput int64
|
||||
DurationMs int64
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX"`
|
||||
}
|
||||
|
||||
// TableName returns the table name for UsageLog.
|
||||
func (UsageLog) TableName() string {
|
||||
return "ai_usage_log"
|
||||
}
|
||||
|
||||
// GetOrgSetting returns the AI settings for an org, or nil if not configured.
|
||||
func GetOrgSetting(ctx context.Context, orgID int64) (*OrgSetting, error) {
|
||||
setting := &OrgSetting{OrgID: orgID}
|
||||
has, err := db.GetEngine(ctx).Where("org_id = ?", orgID).Get(setting)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !has {
|
||||
return nil, nil
|
||||
}
|
||||
return setting, nil
|
||||
}
|
||||
|
||||
// GetRepoSetting returns the AI settings for a repo, or nil if not configured.
|
||||
func GetRepoSetting(ctx context.Context, repoID int64) (*RepoSetting, error) {
|
||||
setting := &RepoSetting{RepoID: repoID}
|
||||
has, err := db.GetEngine(ctx).Where("repo_id = ?", repoID).Get(setting)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !has {
|
||||
return nil, nil
|
||||
}
|
||||
return setting, nil
|
||||
}
|
||||
|
||||
// CreateOrgSetting inserts a new org AI setting.
|
||||
func CreateOrgSetting(ctx context.Context, setting *OrgSetting) error {
|
||||
setting.CreatedUnix = timeutil.TimeStampNow()
|
||||
setting.UpdatedUnix = timeutil.TimeStampNow()
|
||||
_, err := db.GetEngine(ctx).Insert(setting)
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateOrgSetting updates an existing org AI setting.
|
||||
func UpdateOrgSetting(ctx context.Context, setting *OrgSetting) error {
|
||||
setting.UpdatedUnix = timeutil.TimeStampNow()
|
||||
_, err := db.GetEngine(ctx).ID(setting.ID).AllCols().Update(setting)
|
||||
return err
|
||||
}
|
||||
|
||||
// CreateRepoSetting inserts a new repo AI setting.
|
||||
func CreateRepoSetting(ctx context.Context, setting *RepoSetting) error {
|
||||
setting.CreatedUnix = timeutil.TimeStampNow()
|
||||
setting.UpdatedUnix = timeutil.TimeStampNow()
|
||||
_, err := db.GetEngine(ctx).Insert(setting)
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateRepoSetting updates an existing repo AI setting.
|
||||
func UpdateRepoSetting(ctx context.Context, setting *RepoSetting) error {
|
||||
setting.UpdatedUnix = timeutil.TimeStampNow()
|
||||
_, err := db.GetEngine(ctx).ID(setting.ID).AllCols().Update(setting)
|
||||
return err
|
||||
}
|
||||
|
||||
// LogUsage records an AI usage event.
|
||||
func LogUsage(ctx context.Context, log *UsageLog) error {
|
||||
log.CreatedUnix = timeutil.TimeStampNow()
|
||||
_, err := db.GetEngine(ctx).Insert(log)
|
||||
return err
|
||||
}
|
||||
@@ -429,7 +429,7 @@ func prepareMigrationTasks() []*migration {
|
||||
newMigration(349, "Add security scanning tables", v1_27.AddSecurityScanningTables),
|
||||
newMigration(350, "Add issue type definitions table", v1_27.AddIssueTypeDefTable),
|
||||
newMigration(351, "Add CDN public flag to attachments", v1_27.AddAttachmentCDNPublic),
|
||||
newMigration(352, "Add version prefix to repo manifest", v1_27.AddManifestVersionPrefix),
|
||||
newMigration(352, "Add version prefix and element name to repo manifest", v1_27.AddManifestVersionPrefixAndElement),
|
||||
}
|
||||
return preparedMigrations
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright 2026 The MokoGitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_27
|
||||
|
||||
import (
|
||||
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
|
||||
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
type aiOrgSetting struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
OrgID int64 `xorm:"UNIQUE NOT NULL"`
|
||||
Enabled bool `xorm:"NOT NULL DEFAULT true"`
|
||||
APIKeyEncrypted string `xorm:"TEXT"`
|
||||
Model string `xorm:"VARCHAR(50) NOT NULL DEFAULT 'claude-sonnet-4-6'"`
|
||||
RateLimitRequests int `xorm:"NOT NULL DEFAULT 100"`
|
||||
RateLimitTokensMonth int64 `xorm:"NOT NULL DEFAULT 5000000"`
|
||||
CreatedUnix timeutil.TimeStamp
|
||||
UpdatedUnix timeutil.TimeStamp
|
||||
}
|
||||
|
||||
func (aiOrgSetting) TableName() string {
|
||||
return "ai_org_setting"
|
||||
}
|
||||
|
||||
type aiRepoSetting struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
RepoID int64 `xorm:"UNIQUE NOT NULL"`
|
||||
Enabled bool `xorm:"NOT NULL DEFAULT true"`
|
||||
AutoReview bool `xorm:"NOT NULL DEFAULT true"`
|
||||
Strictness string `xorm:"VARCHAR(20) NOT NULL DEFAULT 'standard'"`
|
||||
IgnorePatterns string `xorm:"TEXT"`
|
||||
CreatedUnix timeutil.TimeStamp
|
||||
UpdatedUnix timeutil.TimeStamp
|
||||
}
|
||||
|
||||
func (aiRepoSetting) TableName() string {
|
||||
return "ai_repo_setting"
|
||||
}
|
||||
|
||||
type aiUsageLog struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
OrgID int64 `xorm:"INDEX NOT NULL"`
|
||||
RepoID int64 `xorm:"INDEX NOT NULL"`
|
||||
TriggeredByID int64
|
||||
ActionType string `xorm:"VARCHAR(20) NOT NULL"`
|
||||
Model string `xorm:"VARCHAR(50)"`
|
||||
TokensInput int64
|
||||
TokensOutput int64
|
||||
DurationMs int64
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX"`
|
||||
}
|
||||
|
||||
func (aiUsageLog) TableName() string {
|
||||
return "ai_usage_log"
|
||||
}
|
||||
|
||||
func AddAITables(x *xorm.Engine) error {
|
||||
return x.Sync(new(aiOrgSetting), new(aiRepoSetting), new(aiUsageLog))
|
||||
}
|
||||
@@ -5,10 +5,11 @@ package v1_27
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
// AddManifestVersionPrefix adds the version_prefix column to the repo_manifest table.
|
||||
func AddManifestVersionPrefix(x *xorm.Engine) error {
|
||||
// AddManifestVersionPrefixAndElement adds version_prefix and element_name columns to repo_manifest.
|
||||
func AddManifestVersionPrefixAndElement(x *xorm.Engine) error {
|
||||
type RepoManifest struct {
|
||||
VersionPrefix string `xorm:"TEXT 'version_prefix'"`
|
||||
ElementName string `xorm:"TEXT 'element_name'"`
|
||||
}
|
||||
return x.Sync(new(RepoManifest))
|
||||
}
|
||||
|
||||
@@ -35,7 +35,8 @@ type RepoManifest struct {
|
||||
StandardsSource string `xorm:"TEXT 'standards_source'"` // URL to standards repo
|
||||
|
||||
// versioning
|
||||
VersionPrefix string `xorm:"TEXT 'version_prefix'"` // tag prefix stripped for version display, e.g. "v1.26.1-moko."
|
||||
VersionPrefix string `xorm:"TEXT 'version_prefix'"` // tag prefix stripped for version display, e.g. "v1.26.1-moko."
|
||||
ElementName string `xorm:"TEXT 'element_name'"` // full element name override, e.g. "pkg_mokowaas" (auto-constructed if empty)
|
||||
|
||||
// build section
|
||||
Language string `xorm:"VARCHAR(50) 'language'"` // Go, PHP, TypeScript, etc.
|
||||
@@ -50,6 +51,45 @@ func (RepoManifest) TableName() string {
|
||||
return "repo_manifest"
|
||||
}
|
||||
|
||||
// joomlaTypePrefix maps Joomla extension types to their element name prefixes.
|
||||
var joomlaTypePrefix = map[string]string{
|
||||
"component": "com_",
|
||||
"module": "mod_",
|
||||
"plugin": "plg_",
|
||||
"package": "pkg_",
|
||||
"template": "tpl_",
|
||||
"library": "lib_",
|
||||
"file": "file_",
|
||||
}
|
||||
|
||||
// AutoElementName returns the auto-constructed Joomla element name (e.g. pkg_mokowaas).
|
||||
func (m *RepoManifest) AutoElementName() string {
|
||||
if m.Name == "" || m.PackageType == "" {
|
||||
return ""
|
||||
}
|
||||
if prefix, ok := joomlaTypePrefix[m.PackageType]; ok {
|
||||
return prefix + m.Name
|
||||
}
|
||||
return m.Name
|
||||
}
|
||||
|
||||
// FullElementName returns the effective element name: override if set, otherwise auto-constructed.
|
||||
func (m *RepoManifest) FullElementName() string {
|
||||
if m.ElementName != "" {
|
||||
return m.ElementName
|
||||
}
|
||||
return m.AutoElementName()
|
||||
}
|
||||
|
||||
// ElementNameMismatch returns true if an override is set that differs from the auto-constructed name.
|
||||
func (m *RepoManifest) ElementNameMismatch() bool {
|
||||
if m.ElementName == "" {
|
||||
return false
|
||||
}
|
||||
auto := m.AutoElementName()
|
||||
return auto != "" && m.ElementName != auto
|
||||
}
|
||||
|
||||
// GetRepoManifest returns the manifest for a repo, or nil if none exists.
|
||||
func GetRepoManifest(ctx context.Context, repoID int64) (*RepoManifest, error) {
|
||||
m := new(RepoManifest)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright 2026 The MokoGitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package setting
|
||||
|
||||
// AI settings
|
||||
var (
|
||||
AI = struct {
|
||||
Enabled bool
|
||||
DefaultModel string `ini:"DEFAULT_MODEL"`
|
||||
DefaultKey string `ini:"DEFAULT_API_KEY"`
|
||||
ClaudeBinPath string `ini:"CLAUDE_BIN_PATH"`
|
||||
}{
|
||||
Enabled: false,
|
||||
DefaultModel: "claude-sonnet-4-6",
|
||||
}
|
||||
)
|
||||
|
||||
func loadAIFrom(rootCfg ConfigProvider) {
|
||||
sec := rootCfg.Section("ai")
|
||||
AI.Enabled = sec.Key("ENABLED").MustBool(AI.Enabled)
|
||||
AI.DefaultModel = sec.Key("DEFAULT_MODEL").MustString(AI.DefaultModel)
|
||||
AI.DefaultKey = sec.Key("DEFAULT_API_KEY").String()
|
||||
AI.ClaudeBinPath = sec.Key("CLAUDE_BIN_PATH").MustString("claude")
|
||||
}
|
||||
@@ -2737,6 +2737,12 @@
|
||||
"repo.settings.manifest_desc": "Project identity, governance, and build settings from the MokoPlatform manifest. These are accessible via API for Actions workflows and the MokoPlatform CLI.",
|
||||
"repo.settings.manifest_identity": "Identity",
|
||||
"repo.settings.manifest_name": "Project Name",
|
||||
"repo.settings.manifest_element_name": "Element Name",
|
||||
"repo.settings.manifest_element_name_help": "Base name used to construct the Joomla element identifier (e.g. 'mokowaas'). Combined with the extension type to produce the full element name.",
|
||||
"repo.settings.manifest_element_full": "Full Element Name",
|
||||
"repo.settings.manifest_element_full_help": "Auto-constructed from type + name. Leave blank to use the default, or override for non-standard naming.",
|
||||
"repo.settings.manifest_element_mismatch": "Warning: this overrides the auto-constructed name '%s'. Make sure this matches your Joomla extension's element identifier.",
|
||||
"repo.settings.manifest_package_type_help": "Maps to the Joomla extension type and determines the element prefix (com_, mod_, plg_, pkg_, tpl_, lib_, file_).",
|
||||
"repo.settings.manifest_org": "Organization",
|
||||
"repo.settings.manifest_description": "Description",
|
||||
"repo.settings.manifest_version": "Version",
|
||||
|
||||
@@ -20,6 +20,7 @@ type apiManifest struct {
|
||||
LicenseSPDX string `json:"license_spdx"`
|
||||
LicenseName string `json:"license_name"`
|
||||
VersionPrefix string `json:"version_prefix"`
|
||||
ElementName string `json:"element_name"`
|
||||
Platform string `json:"platform"`
|
||||
StandardsVersion string `json:"standards_version"`
|
||||
StandardsSource string `json:"standards_source"`
|
||||
@@ -62,6 +63,7 @@ func GetRepoManifest(ctx *context.APIContext) {
|
||||
LicenseSPDX: m.LicenseSPDX,
|
||||
LicenseName: m.LicenseName,
|
||||
VersionPrefix: m.VersionPrefix,
|
||||
ElementName: m.FullElementName(),
|
||||
Platform: m.Platform,
|
||||
StandardsVersion: m.StandardsVersion,
|
||||
StandardsSource: m.StandardsSource,
|
||||
@@ -98,6 +100,7 @@ func UpdateRepoManifest(ctx *context.APIContext) {
|
||||
LicenseSPDX: req.LicenseSPDX,
|
||||
LicenseName: req.LicenseName,
|
||||
VersionPrefix: req.VersionPrefix,
|
||||
ElementName: req.ElementName,
|
||||
Platform: req.Platform,
|
||||
StandardsVersion: req.StandardsVersion,
|
||||
StandardsSource: req.StandardsSource,
|
||||
@@ -119,6 +122,7 @@ func UpdateRepoManifest(ctx *context.APIContext) {
|
||||
LicenseSPDX: m.LicenseSPDX,
|
||||
LicenseName: m.LicenseName,
|
||||
VersionPrefix: m.VersionPrefix,
|
||||
ElementName: m.FullElementName(),
|
||||
Platform: m.Platform,
|
||||
StandardsVersion: m.StandardsVersion,
|
||||
StandardsSource: m.StandardsSource,
|
||||
|
||||
@@ -94,6 +94,7 @@ func ManifestSettingsPost(ctx *context.Context) {
|
||||
LicenseSPDX: ctx.FormString("license_spdx"),
|
||||
LicenseName: ctx.FormString("license_name"),
|
||||
VersionPrefix: ctx.FormString("version_prefix"),
|
||||
ElementName: ctx.FormString("element_name"),
|
||||
Platform: ctx.FormString("platform"),
|
||||
StandardsVersion: ctx.FormString("standards_version"),
|
||||
StandardsSource: ctx.FormString("standards_source"),
|
||||
|
||||
@@ -14,18 +14,20 @@ import (
|
||||
|
||||
// manifestXML mirrors the .mokogitea/manifest.xml schema for XML parsing.
|
||||
type manifestXML struct {
|
||||
XMLName xml.Name `xml:"moko-platform"`
|
||||
XMLName xml.Name `xml:"mokoplatform"`
|
||||
Identity manifestIdentity `xml:"identity"`
|
||||
Governance manifestGovernance `xml:"governance"`
|
||||
Build manifestBuild `xml:"build"`
|
||||
}
|
||||
|
||||
type manifestIdentity struct {
|
||||
Name string `xml:"name"`
|
||||
Org string `xml:"org"`
|
||||
Description string `xml:"description"`
|
||||
Version string `xml:"version"`
|
||||
License manifestLicense `xml:"license"`
|
||||
Name string `xml:"name"`
|
||||
Org string `xml:"org"`
|
||||
Description string `xml:"description"`
|
||||
Version string `xml:"version"`
|
||||
VersionPrefix string `xml:"version-prefix"`
|
||||
ElementName string `xml:"element-name"`
|
||||
License manifestLicense `xml:"license"`
|
||||
}
|
||||
|
||||
type manifestLicense struct {
|
||||
@@ -79,6 +81,8 @@ func SyncManifestFromCommit(ctx context.Context, repo *repo_model.Repository, co
|
||||
Org: mxml.Identity.Org,
|
||||
Description: mxml.Identity.Description,
|
||||
Version: mxml.Identity.Version,
|
||||
VersionPrefix: mxml.Identity.VersionPrefix,
|
||||
ElementName: mxml.Identity.ElementName,
|
||||
LicenseSPDX: mxml.Identity.License.SPDX,
|
||||
LicenseName: mxml.Identity.License.Name,
|
||||
Platform: mxml.Governance.Platform,
|
||||
|
||||
@@ -11,8 +11,14 @@
|
||||
<h5 class="ui dividing header">{{ctx.Locale.Tr "repo.settings.manifest_identity"}}</h5>
|
||||
<div class="two fields">
|
||||
<div class="field">
|
||||
<label>{{ctx.Locale.Tr "repo.settings.manifest_name"}}</label>
|
||||
<input name="name" value="{{.Manifest.Name}}" placeholder="Project name">
|
||||
{{if eq .Manifest.Platform "joomla"}}
|
||||
<label>{{ctx.Locale.Tr "repo.settings.manifest_element_name"}}</label>
|
||||
<input name="name" value="{{.Manifest.Name}}" placeholder="e.g. mokowaas">
|
||||
<p class="help">{{ctx.Locale.Tr "repo.settings.manifest_element_name_help"}}</p>
|
||||
{{else}}
|
||||
<label>{{ctx.Locale.Tr "repo.settings.manifest_name"}}</label>
|
||||
<input name="name" value="{{.Manifest.Name}}" placeholder="Project name">
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>{{ctx.Locale.Tr "repo.settings.manifest_org"}}</label>
|
||||
@@ -45,7 +51,7 @@
|
||||
<select name="platform" class="ui dropdown">
|
||||
<option value="">—</option>
|
||||
{{$platform := .Manifest.Platform}}
|
||||
{{range $val := StringUtils.Split "joomla,dolibarr,go,mcp,platform,generic" ","}}
|
||||
{{range $val := StringUtils.Split "joomla,wordpress,dolibarr,go,mcp,platform,generic" ","}}
|
||||
<option value="{{$val}}" {{if eq $val $platform}}selected{{end}}>{{$val}}</option>
|
||||
{{end}}
|
||||
</select>
|
||||
@@ -82,6 +88,17 @@
|
||||
<option value="{{$val}}" {{if eq $val $pkgType}}selected{{end}}>{{$val}}</option>
|
||||
{{end}}
|
||||
</select>
|
||||
<p class="help">{{ctx.Locale.Tr "repo.settings.manifest_package_type_help"}}</p>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="field">
|
||||
<label>{{ctx.Locale.Tr "repo.settings.manifest_element_full"}}</label>
|
||||
<input name="element_name" value="{{.Manifest.ElementName}}" placeholder="{{.Manifest.AutoElementName}}">
|
||||
{{if .Manifest.ElementNameMismatch}}
|
||||
<p class="help tw-text-yellow-600">{{ctx.Locale.Tr "repo.settings.manifest_element_mismatch" .Manifest.AutoElementName}}</p>
|
||||
{{else}}
|
||||
<p class="help">{{ctx.Locale.Tr "repo.settings.manifest_element_full_help"}}</p>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="field">
|
||||
|
||||
Reference in New Issue
Block a user