Compare commits

...

29 Commits

Author SHA1 Message Date
jmiller 056eb7d3c4 chore: sync notify.yml from Template-Generic [skip ci] 2026-07-05 00:05:09 +00:00
jmiller 0492448ab5 chore: sync cleanup.yml from Template-Generic [skip ci] 2026-07-05 00:04:56 +00:00
jmiller 377dd019be chore: sync auto-release.yml from Template-Generic [skip ci] 2026-07-04 23:27:10 +00:00
jmiller 5ffed39449 Merge pull request 'fix: render org teams list and make issue type editable (#720, #721)' (#726) from fix/team-list-and-issue-type-editable into main
Deploy MokoGitea / deploy (push) Failing after 5m1s
2026-07-04 21:31:56 +00:00
jmiller 0cc569aef6 fix: render org teams list and make issue type editable (#720, #721)
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 2s
Universal: PR Check / Validate PR (pull_request) Successful in 14s
Generic: Project CI / Lint & Validate (pull_request) Successful in 57s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 1m15s
PR RC Release / Build RC Release (pull_request) Successful in 2m18s
Universal: PR Check / Secret Scan (pull_request) Successful in 2m19s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Failing after 1m10s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Failing after 9m20s
Generic: Project CI / Tests (pull_request) Has been cancelled
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: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
#720: org Teams page wrote ctx.Data["OrgListTeams"] but the template iterates .Teams, so no teams rendered. Use the canonical Teams key (matches org/home.go). #721: issue type sidebar gated editing on a FieldEditFlags data key that no handler sets (always nil -> always read-only). Use HasIssuesOrPullsWritePermission like the priority field; the /custom-type endpoint is already protected by reqRepoIssuesOrPullsWriter.
2026-07-04 16:27:32 -05:00
jmiller 4ed45a5916 chore: sync pr-check.yml from Template-Generic [skip ci] 2026-07-04 20:27:57 +00:00
jmiller ea87b3db97 chore: sync pr-check.yml from Template-Generic [skip ci] 2026-07-04 20:22:43 +00:00
jmiller d77b82a8af chore: sync ci-generic.yml from Template-Generic [skip ci] 2026-07-04 20:22:34 +00:00
jmiller 22b0b14ea8 chore: sync pr-check.yml from Template-Generic [skip ci] 2026-07-04 19:38:21 +00:00
jmiller 1256f57d40 chore: sync ci-generic.yml from Template-Generic [skip ci] 2026-07-04 19:38:11 +00:00
jmiller 05763eb661 chore: sync branch-cleanup.yml from Template-Generic [skip ci] 2026-07-04 19:37:58 +00:00
jmiller 0c45a2fda3 chore: sync sync-on-merge.yml from Template-Generic [skip ci] 2026-07-04 19:05:30 +00:00
jmiller 8680fd1cab chore: sync pre-release.yml from Template-Generic [skip ci] 2026-07-04 19:05:10 +00:00
jmiller adf0e923df chore: sync pr-check.yml from Template-Generic [skip ci] 2026-07-04 19:04:47 +00:00
jmiller 296df7792a chore: sync notify.yml from Template-Generic [skip ci] 2026-07-04 19:04:37 +00:00
jmiller 51332a587d chore: sync cleanup.yml from Template-Generic [skip ci] 2026-07-04 19:04:27 +00:00
jmiller 8fc2700c16 chore: sync ci-generic.yml from Template-Generic [skip ci] 2026-07-04 19:04:20 +00:00
jmiller 844b4b6e81 chore: sync auto-release.yml from Template-Generic [skip ci] 2026-07-04 19:04:10 +00:00
jmiller cb9516b79b Merge pull request 'fix: support radio inputs in admin system config form' (#724) from fix/admin-config-radio into main
Deploy MokoGitea / deploy (push) Failing after 3m57s
2026-07-04 19:01:33 +00:00
jmiller aea4370845 ci: no-op PR RC Release when updates.xml is absent
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
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) Successful in 11s
Generic: Project CI / Lint & Validate (pull_request) Successful in 33s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 49s
PR RC Release / Build RC Release (pull_request) Successful in 1m34s
Universal: PR Check / Secret Scan (pull_request) Successful in 1m36s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Failing after 55s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Successful in 8m57s
Generic: Project CI / Tests (pull_request) Has been cancelled
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: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
The RC release workflow drives a Joomla-style updates.xml update stream. On a generic repo with no updates.xml, the Determine RC version step ran sed on a missing file and aborted under set -e (exit 2). Detect updates.xml presence and gate the update-stream steps (edit/create-release/commit) on it so the job succeeds and no-ops when there is nothing to package.
2026-07-04 13:53:15 -05:00
jmiller fc234bc911 fix: remove dangling mcp-mokogitea-api submodule gitlink
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Successful in 11s
Generic: Project CI / Lint & Validate (pull_request) Successful in 39s
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
PR RC Release / Build RC Release (pull_request) Failing after 1m11s
Universal: PR Check / Secret Scan (pull_request) Successful in 1m12s
Generic: Project CI / Tests (pull_request) Has been cancelled
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: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
The tree carried a gitlink at mcp-mokogitea-api (mode 160000) with no .gitmodules entry, so git submodule update --init --recursive failed with exit 128 at checkout, breaking every PR build/release job. mcp-mokogitea-api is a separate repo, not a submodule; remove the gitlink from the index (keeping the local working-tree clone) and gitignore the path so it can't be re-added.
2026-07-04 13:46:35 -05:00
jmiller b252e9569f ci: allow fix/patch branches to target main and guard missing manifest
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 2s
Universal: PR Check / Validate PR (pull_request) Successful in 11s
Generic: Project CI / Lint & Validate (pull_request) Successful in 36s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Failing after 1m0s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Failing after 57s
Universal: PR Check / Secret Scan (pull_request) Successful in 57s
Generic: Project CI / Tests (pull_request) Has been cancelled
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: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
Branch policy in pr-check.yml only allowed fix/* and patch/* to target dev/rc, blocking fix/* PRs to main despite the documented policy. Allow fix/* -> main and patch/* -> main. Also guard the Detect platform step for a missing .mokogitea/manifest.xml (removed in favor of the metadata API) so it no longer aborts the Validate PR job under set -e.
2026-07-04 13:36:47 -05:00
jmiller efb0433412 fix: preserve server-rendered radio default when config value is empty
Universal: PR Check / Branch Policy (pull_request) Failing after 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 11s
Generic: Project CI / Lint & Validate (pull_request) Successful in 37s
PR RC Release / Build RC Release (pull_request) Failing after 1m3s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Failing after 1m5s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Universal: PR Check / Secret Scan (pull_request) Successful in 1m9s
Generic: Project CI / Tests (pull_request) Has been cancelled
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: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
LandingPageType.Mode defaults to "" (Go zero value), and the template renders the home radio as checked for an empty Mode. The initial radio fill would evaluate home.checked = ("home" === "") = false, unchecking the default on a fresh install. Skip assignment when the config value is empty so the server-rendered selection is preserved. Adds a test for the empty-value case.
2026-07-04 13:15:10 -05:00
jmiller 982e45a56e fix: support radio inputs in admin system config form
Universal: PR Check / Branch Policy (pull_request) Failing after 1s
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 11s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Failing after 38s
Universal: Build & Release / Promote to RC (pull_request) Failing after 8s
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Generic: Project CI / Lint & Validate (pull_request) Successful in 39s
Universal: PR Check / Secret Scan (pull_request) Successful in 43s
Generic: Project CI / Tests (pull_request) Has been cancelled
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: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
The system config form JS (config.ts) only mapped checkbox, text, textarea, and datetime-local elements. The fork landing_page.tmpl uses radio inputs for the Mode field, so fillFromSystemConfig() hit unsupportedElement() and threw, aborting all JS init on the admin settings page.

Add radio handling in both directions: fill checks the option whose value matches the config value; collect returns the checked option's value and skips/nulls unchecked radios so a group resolves to exactly one value. Adds a radio-group test case.
2026-07-04 01:20:43 -05:00
jmiller 78328146e5 Merge pull request 'fix: remove orphaned deploy-manual workflow' (#718) from fix/remove-deploy-manual into main
fix: remove orphaned deploy-manual workflow [skip ci]
2026-06-30 18:33:36 +00:00
jmiller 84c6a94333 fix: remove orphaned deploy-manual workflow [skip ci] 2026-06-30 18:07:04 +00:00
jmiller 11b2195bdf chore: sync auto-release.yml from Template-Generic [skip ci] 2026-06-28 20:07:10 +00:00
jmiller f8a91ed34e release: code security scanner (#552)
Deploy MokoGitea / deploy (push) Failing after 5m9s
Code security scanner with 22 OWASP pattern detection rules across 7 CWE categories (SQL injection, XSS, command injection, path traversal, insecure deserialization, hardcoded credentials, weak cryptography). Language-filtered scanning for Go, PHP, Python, JS/TS, Java, C#, Ruby.
2026-06-28 19:00:33 +00:00
jmiller 108b19dcc8 chore: sync pr-check.yml from Template-Generic [skip ci] 2026-06-28 11:12:11 +00:00
17 changed files with 170 additions and 175 deletions
+3
View File
@@ -120,3 +120,6 @@ prime/
# A Makefile for custom make targets
Makefile.local
# Local clone of the MCP server (separate repo, not a submodule of this project)
/mcp-mokogitea-api/
+51 -13
View File
@@ -7,7 +7,7 @@
# INGROUP: mokocli.Release
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/mokocli
# PATH: /templates/workflows/universal/auto-release.yml.template
# VERSION: 05.00.00
# VERSION: 05.01.00
# BRIEF: Universal build & release detects platform from manifest.xml
#
# +=======================================================================+
@@ -64,10 +64,14 @@ jobs:
promote-rc:
name: Promote to RC
runs-on: release
# Skip on template repos (Template-*) — they scaffold other repos and do not 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')
!startsWith(github.event.repository.name, 'Template-') &&
(
(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
@@ -75,6 +79,7 @@ jobs:
with:
token: ${{ secrets.MOKOGITEA_TOKEN }}
fetch-depth: 1
submodules: recursive
- name: Setup mokocli tools
env:
@@ -90,7 +95,7 @@ jobs:
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/mokocli
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoCLI.git
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
cd /tmp/mokocli
composer install --no-dev --no-interaction --quiet
@@ -99,11 +104,39 @@ jobs:
- name: Rename branch to rc
run: |
php ${MOKO_CLI}/branch_rename.php \
--from "${{ github.event.pull_request.head.ref || 'dev' }}" --to rc \
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
--api-base "${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" \
--pr "${{ github.event.pull_request.number }}"
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
AUTH="Authorization: token ${{ secrets.MOKOGITEA_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. If rc already exists (a protected branch that
# cannot be deleted), force-update its ref in place instead of delete+recreate:
# deleting a protected branch fails, which then makes the recreate return HTTP 409.
if curl -sf -o /dev/null -H "$AUTH" "${API_BASE}/branches/rc"; then
echo "rc exists - force-updating to ${FROM} (${SRC_SHA})"
curl -sf -X PATCH -H "$AUTH" -H "Content-Type: application/json" \
"${API_BASE}/git/refs/heads/rc" -d "{\"sha\":\"${SRC_SHA}\",\"force\":true}" \
|| { echo "::error::Failed to force-update rc (CI token needs force-push on the protected rc branch)"; exit 1; }
else
echo "Creating rc from ${FROM}"
curl -sf -X POST -H "$AUTH" -H "Content-Type: application/json" \
"${API_BASE}/branches" -d "{\"new_branch_name\":\"rc\",\"old_branch_name\":\"${FROM}\"}" \
|| { echo "::error::Failed to create rc from ${FROM}"; exit 1; }
fi
# Repoint the PR at rc, then delete the old source branch (non-fatal).
if [ -n "$PR" ]; then
curl -s -X PATCH -H "$AUTH" -H "Content-Type: application/json" \
"${API_BASE}/pulls/${PR}" -d '{"head":"rc"}' >/dev/null || true
fi
curl -s -X DELETE -H "$AUTH" "${API_BASE}/branches/${FROM}" >/dev/null || true
echo "Renamed ${FROM} -> rc"
- name: Checkout rc and configure git
run: |
@@ -163,9 +196,13 @@ jobs:
release:
name: Build & Release Pipeline
runs-on: release
# Skip on template repos (Template-*) — they scaffold other repos and do not release.
if: >-
github.event.pull_request.merged == true ||
(github.event_name == 'workflow_dispatch' && inputs.action != 'promote-rc')
!startsWith(github.event.repository.name, 'Template-') &&
(
github.event.pull_request.merged == true ||
(github.event_name == 'workflow_dispatch' && inputs.action != 'promote-rc')
)
steps:
- name: Checkout repository
@@ -173,6 +210,7 @@ jobs:
with:
token: ${{ secrets.MOKOGITEA_TOKEN }}
fetch-depth: 0
submodules: recursive
- name: Configure git for bot pushes
run: |
@@ -208,7 +246,7 @@ jobs:
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/mokocli
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoCLI.git
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
cd /tmp/mokocli
composer install --no-dev --no-interaction --quiet
+2 -1
View File
@@ -33,7 +33,8 @@ jobs:
run: |
BRANCH="${{ github.event.pull_request.head.ref }}"
API="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}/api/v1/repos/${{ github.repository }}/branches"
ENCODED=$(php -r "echo rawurlencode('${BRANCH}');")
# URL-encode the branch name's slashes (no PHP dependency on the runner)
ENCODED=$(printf '%s' "${BRANCH}" | sed 's|/|%2F|g')
STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X DELETE \
-H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \
+6 -1
View File
@@ -6,7 +6,7 @@
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.CI
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.gitea/workflows/ci-generic.yml
# PATH: /.mokogitea/workflows/ci-generic.yml
# VERSION: 01.00.00
# BRIEF: CI pipeline — lint, validate, and test for generic projects (PHP + Node.js)
@@ -32,6 +32,8 @@ jobs:
lint:
name: Lint & Validate
runs-on: ubuntu-latest
# Skip on template repos (Template-*) — they hold placeholder scaffolding, not buildable source.
if: ${{ !startsWith(github.event.repository.name, 'Template-') }}
steps:
- name: Checkout
@@ -130,6 +132,9 @@ jobs:
name: Tests
runs-on: ubuntu-latest
needs: lint
# Run only when lint succeeded; always() forces evaluation so a skipped
# lint (e.g. template repos) skips this job cleanly instead of hanging.
if: ${{ always() && needs.lint.result == 'success' }}
steps:
- name: Checkout
+2 -2
View File
@@ -6,7 +6,7 @@
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Maintenance
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards
# PATH: /.gitea/workflows/cleanup.yml
# PATH: /.mokogitea/workflows/cleanup.yml
# VERSION: 01.00.00
# BRIEF: Scheduled cleanup — delete merged branches and old workflow runs
@@ -50,7 +50,7 @@ jobs:
for BRANCH in $BRANCHES; do
# Skip protected branches
case "$BRANCH" in
main|master|develop|release/*|hotfix/*) continue ;;
main|master|dev|develop|rc|beta|alpha|release|release/*|production|stable|staging|hotfix/*|version/*) continue ;;
esac
# Check if branch is merged into main
+12 -3
View File
@@ -47,6 +47,15 @@ jobs:
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
# This RC flow drives a Joomla-style update stream (updates.xml). Repos that don't ship
# one (e.g. generic Go/TS) have nothing to package here, so no-op cleanly instead of
# aborting under `set -e` when the file is absent.
if [ ! -f updates.xml ]; then
echo "has_updates=false" >> "$GITHUB_OUTPUT"
echo "No updates.xml in this repo — skipping RC update-stream packaging"
exit 0
fi
echo "has_updates=true" >> "$GITHUB_OUTPUT"
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}"
@@ -56,7 +65,7 @@ jobs:
echo "RC version: $RC_VERSION (tag: $RC_TAG)"
- name: Update updates.xml RC channel
if: steps.guard.outputs.skip != 'true'
if: steps.guard.outputs.skip != 'true' && steps.version.outputs.has_updates == 'true'
env:
RC_VERSION: ${{ steps.version.outputs.version }}
RC_TAG: ${{ steps.version.outputs.tag }}
@@ -106,7 +115,7 @@ jobs:
PYEOF
- name: Create RC release
if: steps.guard.outputs.skip != 'true'
if: steps.guard.outputs.skip != 'true' && steps.version.outputs.has_updates == 'true'
env:
GITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
RC_TAG: ${{ steps.version.outputs.tag }}
@@ -153,7 +162,7 @@ jobs:
PYEOF
- name: Commit updates.xml
if: steps.guard.outputs.skip != 'true'
if: steps.guard.outputs.skip != 'true' && steps.version.outputs.has_updates == 'true'
env:
GITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
HEAD_REF: ${{ github.event.pull_request.head.ref }}
-126
View File
@@ -1,126 +0,0 @@
# 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:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN || github.token }}
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN || github.token }}
MOKO_CLONE_HOST: ${{ secrets.MOKOGITEA_TOKEN && 'git.mokoconsulting.tech/MokoConsulting' || 'github.com/mokoconsulting-tech' }}
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.MOKOGITEA_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
+4 -4
View File
@@ -6,7 +6,7 @@
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Notifications
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards
# PATH: /.gitea/workflows/notify.yml
# PATH: /.mokogitea/workflows/notify.yml
# VERSION: 01.00.00
# BRIEF: Push notifications via ntfy on release success or workflow failure
@@ -15,9 +15,9 @@ name: "Universal: Notifications"
on:
workflow_run:
workflows:
- "Joomla Build & Release"
- "Joomla Extension CI"
- "Deploy"
- "Universal: Build & Release"
- "Joomla: Extension CI"
- "Generic: Project CI"
types:
- completed
+17 -20
View File
@@ -4,8 +4,8 @@
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.CI
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/moko-platform
# INGROUP: mokocli.CI
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/mokocli
# PATH: /templates/workflows/universal/pr-check.yml.template
# VERSION: 09.23.00
# BRIEF: PR gate — branch policy + code validation before merge
@@ -47,15 +47,15 @@ jobs:
fi
;;
fix/*|bugfix/*)
if [ "$BASE" != "main" ] && [ "$BASE" != "dev" ]; then
if [ "$BASE" != "dev" ] && [ "$BASE" != "main" ]; then
ALLOWED=false
REASON="Fix branches must target 'main' or 'dev', not '${BASE}'"
REASON="Fix branches must target 'dev' or 'main', not '${BASE}'"
fi
;;
patch/*)
if [ "$BASE" != "main" ] && [ "$BASE" != "dev" ] && [ "$BASE" != "rc" ]; then
if [ "$BASE" != "dev" ] && [ "$BASE" != "rc" ] && [ "$BASE" != "main" ]; then
ALLOWED=false
REASON="Patch branches must target 'main', 'dev', or 'rc', not '${BASE}'"
REASON="Patch branches must target 'dev', 'rc', or 'main', not '${BASE}'"
fi
;;
hotfix/*)
@@ -86,11 +86,11 @@ jobs:
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Allowed merge paths:" >> $GITHUB_STEP_SUMMARY
echo "- \`feature/*\` → \`dev\`" >> $GITHUB_STEP_SUMMARY
echo "- \`fix/*\` → \`main\` or \`dev\`" >> $GITHUB_STEP_SUMMARY
echo "- \`patch/*\` → \`main\`, \`dev\`, or \`rc\`" >> $GITHUB_STEP_SUMMARY
echo "- \`fix/*\` → \`dev\` or \`main\`" >> $GITHUB_STEP_SUMMARY
echo "- \`patch/*\` → \`dev\`, \`rc\`, or \`main\`" >> $GITHUB_STEP_SUMMARY
echo "- \`hotfix/*\` → \`dev\` or \`main\`" >> $GITHUB_STEP_SUMMARY
echo "- \`dev\` → \`main\`" >> $GITHUB_STEP_SUMMARY
echo "- \`rc\` → \`main\`" >> $GITHUB_STEP_SUMMARY
echo "- \`rc/*\` → \`main\`" >> $GITHUB_STEP_SUMMARY
exit 1
fi
@@ -127,6 +127,8 @@ jobs:
validate:
name: Validate PR
runs-on: ubuntu-latest
# Skip on template repos (Template-*) — no real manifest/source/changelog to validate.
if: ${{ !startsWith(github.event.repository.name, 'Template-') }}
steps:
- name: Checkout
@@ -147,18 +149,10 @@ jobs:
- name: Detect platform
id: platform
env:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
REPO: ${{ github.repository }}
run: |
# Query metadata API for platform (manifest.xml is deprecated)
PLATFORM=""
if [ -n "$MOKOGITEA_TOKEN" ]; then
PLATFORM=$(curl -sf -H "Authorization: token ${MOKOGITEA_TOKEN}" \
"${MOKOGITEA_URL}/api/v1/repos/${REPO}/metadata" 2>/dev/null \
| sed -n 's/.*"platform"\s*:\s*"\([^"]*\)".*/\1/p' | head -1) || true
fi
# Platform comes from the MokoGitea metadata API (public GET); manifest.xml is no longer used.
API="${GITHUB_SERVER_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${GITHUB_REPOSITORY}/metadata"
PLATFORM="$(curl -sf "$API" 2>/dev/null | python3 -c "import sys, json; print(json.load(sys.stdin).get('platform') or '')" 2>/dev/null || true)"
[ -z "$PLATFORM" ] && PLATFORM="generic"
echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT"
echo "Detected platform: $PLATFORM"
@@ -502,6 +496,9 @@ jobs:
name: Build RC Package
runs-on: ubuntu-latest
needs: [branch-policy, validate]
# Run only when both gates succeeded; always() forces evaluation so a skipped
# validate (e.g. template repos) skips this job cleanly instead of hanging.
if: ${{ always() && needs.branch-policy.result == 'success' && needs.validate.result == 'success' }}
steps:
- name: Trigger RC pre-release
+6 -2
View File
@@ -48,9 +48,13 @@ jobs:
build:
name: "Build Pre-Release (${{ inputs.stability || github.ref_name }})"
runs-on: release
# Skip on template repos (Template-*) — they scaffold other repos and do not release.
if: >-
github.event_name == 'workflow_dispatch' ||
github.event_name == 'push'
!startsWith(github.event.repository.name, 'Template-') &&
(
github.event_name == 'workflow_dispatch' ||
github.event_name == 'push'
)
steps:
- name: Checkout
+31
View File
@@ -0,0 +1,31 @@
name: Sync Workflows to Repos
on:
push:
branches:
- main
paths:
- '.mokogitea/workflows/**'
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Checkout mokocli
uses: actions/checkout@v4
with:
repository: MokoConsulting/mokocli
token: ${{ secrets.MOKOGITEA_TOKEN }}
- name: Setup PHP
uses: https://git.mokoconsulting.tech/MokoConsulting/.mokogitea/raw/branch/main/actions/setup-php@v1
with:
php-version: '8.1'
- name: Install dependencies
run: composer install --no-dev --no-interaction
- name: Sync workflows to generic repos
run: php automation/bulk_sync.php --platform generic --org MokoConsulting --workflows-only --auto-merge --token "${{ secrets.MOKOGITEA_TOKEN }}"
env:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
+7
View File
@@ -57,6 +57,13 @@
- Cherry-pick upstream v1.26.4: walk git log context error handling — regression fix (#38185)
### Fixed
- 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 `.mokogitea/manifest.xml` so the Validate PR job no longer aborts under `set -e` (manifest replaced by metadata API)
- Remove dangling `mcp-mokogitea-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)
Submodule mcp-mokogitea-api deleted from dbaf91546e
+1 -1
View File
@@ -98,7 +98,7 @@ func Teams(ctx *context.Context) {
}
}
ctx.Data["OrgListTeams"] = teams
ctx.Data["Teams"] = teams
ctx.Data["Keyword"] = keyword
pager := context.NewPagination(count, setting.UI.MembersPagingNum, page, 5)
pager.AddParamFromRequest(ctx.Req)
+1 -1
View File
@@ -2,7 +2,7 @@
<div class="divider"></div>
<div class="tw-flex tw-items-center tw-justify-between tw-gap-2">
<span class="text grey tw-text-sm">{{ctx.Locale.Tr "repo.issues.type"}}</span>
{{$canModify := and .FieldEditFlags .FieldEditFlags.CustomFields}}
{{$canModify := .HasIssuesOrPullsWritePermission}}
{{if $canModify}}
<form method="post" action="{{.RepoLink}}/issues/{{.Issue.ID}}/custom-type" class="tw-inline">
{{$.CsrfTokenHtml}}
+13
View File
@@ -21,6 +21,17 @@ test('ConfigFormValueMapper', () => {
<input name="struct.SubBoolean" type="checkbox" data-config-value-type="boolean">
<input name="struct.SubTimestamp" type="datetime-local" data-config-value-type="timestamp">
<textarea name="struct.NewKey">new-value</textarea>
<!-- radio group (sub key): only the option matching the config value should be checked and collected -->
<input type="hidden" data-config-dyn-key="landing" data-config-value-json='{"Mode": "explore"}'>
<input name="landing.Mode" type="radio" value="home">
<input name="landing.Mode" type="radio" value="explore">
<input name="landing.Mode" type="radio" value="login">
<!-- radio group with empty value: the server-rendered default (home) must be preserved, not unchecked -->
<input type="hidden" data-config-dyn-key="landingDefault" data-config-value-json='{"Mode": ""}'>
<input name="landingDefault.Mode" type="radio" value="home" checked>
<input name="landingDefault.Mode" type="radio" value="explore">
</form>
`;
@@ -44,5 +55,7 @@ test('ConfigFormValueMapper', () => {
'k-flipped-true': 'true',
'repository.open-with.editor-apps': '[{"DisplayName":"a","OpenURL":"b"}]', // TODO: OPEN-WITH-EDITOR-APP-JSON: it must match backend
'struct': '{"SubBoolean":true,"SubTimestamp":123456780,"OtherKey":"other-value","NewKey":"new-value"}',
'landing': '{"Mode":"explore"}',
'landingDefault': '{"Mode":"home"}',
});
});
+14
View File
@@ -99,6 +99,10 @@ export class ConfigFormValueMapper {
if (el.matches('[type="checkbox"]')) {
if (valType !== 'boolean') requireExplicitValueType(el);
el.checked = Boolean(val ?? el.checked);
} else if (el.matches('[type="radio"]')) {
// a radio group shares one name; check only the option whose value equals the config value.
// when the value is empty (unset), leave the server-rendered default selection untouched.
if (String(val) !== '') el.checked = el.value === String(val);
} else if (el.matches('[type="datetime-local"]')) {
if (valType !== 'timestamp') requireExplicitValueType(el);
if (val) el.value = toDatetimeLocalValue(val);
@@ -120,6 +124,9 @@ export class ConfigFormValueMapper {
// it needs to iterate the "namedElems" to find all the checkboxes with the same name and collect values accordingly,
// and set the namedElems[matchedIdx] to null to avoid duplicate processing.
val = collectCheckboxBooleanValue(el);
} else if (el.matches('[type="radio"]')) {
// only the checked radio of a group reaches here (callers skip unchecked ones); its value is the selection
val = el.value;
} else if (el.matches('[type="datetime-local"]')) {
if (valType !== 'timestamp') requireExplicitValueType(el);
val = Math.floor(new Date(el.value).getTime() / 1000) ?? 0; // NaN is fine to JSON.stringify, it becomes null.
@@ -139,6 +146,12 @@ export class ConfigFormValueMapper {
if (!el) continue;
const subKey = extractElemConfigSubKey(el, dynKey);
if (!subKey) continue; // if not match, skip
// a radio group has N elements sharing the same name; only the checked one carries the value.
// drop the unchecked ones so they neither overwrite the selection here nor leak into the fallback loop.
if (el.matches('[type="radio"]') && !el.checked) {
namedElems[idx] = null;
continue;
}
cfgVal[subKey] = this.collectConfigValueFromElement(el);
namedElems[idx] = null;
}
@@ -194,6 +207,7 @@ export class ConfigFormValueMapper {
// "foo.enabled" => "true"
for (const el of namedElems) {
if (!el) continue;
if (el.matches('[type="radio"]') && !el.checked) continue; // skip unchecked radios of a top-level group
const dynKey = el.name;
const newVal = this.collectConfigValueFromElement(el);
formData.append('key', dynKey);