Public Access
Compare commits
107 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4637dab159 | |||
| b885f12ece | |||
| e99881ad65 | |||
| fd3c847fb1 | |||
| 424fe658ba | |||
| 0ff87f3631 | |||
| 3164f21ba9 | |||
| 713cb61efc | |||
| fa342a278b | |||
| d91baf996e | |||
| 2100a3bec7 | |||
| 8d772df3e7 | |||
| 3972e4fb84 | |||
| 86b8449eba | |||
| 601451867d | |||
| 09ffcdce49 | |||
| a49e0d7b2a | |||
| bc1a111775 | |||
| 98c41c3a53 | |||
| 52ebcde1ff | |||
| ded17c34b8 | |||
| 1b79de20a9 | |||
| bba1cbc845 | |||
| 3f956f5661 | |||
| 9036d20898 | |||
| 7c1edcf813 | |||
| fec5a48b4a | |||
| 468b962aaa | |||
| cc66a79fea | |||
| 660ae5bed4 | |||
| 5ffaf95d20 | |||
| ddfb479bc2 | |||
| 13e2729124 | |||
| 05ee59d75e | |||
| c4bb08073b | |||
| b32556fdef | |||
| c57a7e4b96 | |||
| 5846ccc3e8 | |||
| 6ba0208571 | |||
| 759b04e088 | |||
| 4dfa2d9722 | |||
| 590ad7337a | |||
| c607966e83 | |||
| 97f2226288 | |||
| b1f2c391cb | |||
| 7e4d88eea5 | |||
| 9fdd6c5cf9 | |||
| 113af457d9 | |||
| abd67f6c43 | |||
| d3dce5d24e | |||
| c9592d8e78 | |||
| 6bf6251705 | |||
| 520acd4fee | |||
| a6c4fe0688 | |||
| 3c420284e3 | |||
| 66543c14d3 | |||
| d9908e264a | |||
| 9206f716e1 | |||
| 84633e22e5 | |||
| 510d1248ab | |||
| 8e30fa54b3 | |||
| 1aaec7d8ff | |||
| 5efdaf6c05 | |||
| 448e11568b | |||
| dce0fe0994 | |||
| 2dc115327b | |||
| 4715dba7fc | |||
| 5ab1782715 | |||
| 08db79da17 | |||
| c94564cec6 | |||
| ac52a697e5 | |||
| 57b458b79a | |||
| 2a84b38194 | |||
| 9d9b78b4e9 | |||
| 092543db1c | |||
| 2286514c59 | |||
| 6993f30513 | |||
| 0b30cc5a6d | |||
| 7b0c239dd2 | |||
| cf278cf914 | |||
| fdeacc73c5 | |||
| 117bba7765 | |||
| 65a11a19ac | |||
| fae2eab41b | |||
| f91b05287a | |||
| 43fd64a15b | |||
| 15074fb0ae | |||
| 415b5403be | |||
| 84fdb39d20 | |||
| 44b9e991b5 | |||
| 9b647b2540 | |||
| cedf10bdff | |||
| 8422292b46 | |||
| b1f3487a43 | |||
| c8f346e069 | |||
| 0da62a99e3 | |||
| 60c8309067 | |||
| 12f7ab7e30 | |||
| ccff69d48c | |||
| 8ab44feed5 | |||
| 483a22a13c | |||
| a3b1fb1f11 | |||
| 5e69242320 | |||
| a183787db6 | |||
| 13ab870418 | |||
| 8fd324f60e | |||
| 3ebfe2da8a |
@@ -124,7 +124,8 @@ jobs:
|
||||
"rule_name": "main",
|
||||
"enable_push": true,
|
||||
"enable_push_whitelist": true,
|
||||
"push_whitelist_usernames": ["jmiller"],
|
||||
"push_whitelist_usernames": ["jmiller", "moko-deploy"],
|
||||
"push_whitelist_actions_user": true,
|
||||
"enable_force_push": false,
|
||||
"enable_force_push_allowlist": false,
|
||||
"force_push_allowlist_usernames": [],
|
||||
@@ -140,10 +141,12 @@ jobs:
|
||||
"rule_name": "dev",
|
||||
"enable_push": true,
|
||||
"enable_push_whitelist": true,
|
||||
"push_whitelist_usernames": ["jmiller"],
|
||||
"enable_force_push": false,
|
||||
"enable_force_push_allowlist": false,
|
||||
"force_push_allowlist_usernames": [],
|
||||
"push_whitelist_usernames": ["jmiller", "moko-deploy"],
|
||||
"push_whitelist_actions_user": true,
|
||||
"enable_force_push": true,
|
||||
"enable_force_push_allowlist": true,
|
||||
"force_push_allowlist_usernames": ["jmiller", "moko-deploy"],
|
||||
"force_push_allowlist_actions_user": true,
|
||||
"enable_merge_whitelist": false,
|
||||
"required_approvals": 0,
|
||||
"block_on_rejected_reviews": false,
|
||||
@@ -154,10 +157,12 @@ jobs:
|
||||
"rule_name": "rc",
|
||||
"enable_push": true,
|
||||
"enable_push_whitelist": true,
|
||||
"push_whitelist_usernames": ["jmiller"],
|
||||
"enable_force_push": false,
|
||||
"enable_force_push_allowlist": false,
|
||||
"force_push_allowlist_usernames": [],
|
||||
"push_whitelist_usernames": ["jmiller", "moko-deploy"],
|
||||
"push_whitelist_actions_user": true,
|
||||
"enable_force_push": true,
|
||||
"enable_force_push_allowlist": true,
|
||||
"force_push_allowlist_usernames": ["jmiller", "moko-deploy"],
|
||||
"force_push_allowlist_actions_user": true,
|
||||
"enable_merge_whitelist": false,
|
||||
"required_approvals": 0,
|
||||
"block_on_rejected_reviews": false,
|
||||
@@ -168,7 +173,8 @@ jobs:
|
||||
"rule_name": "beta",
|
||||
"enable_push": true,
|
||||
"enable_push_whitelist": true,
|
||||
"push_whitelist_usernames": ["jmiller"],
|
||||
"push_whitelist_usernames": ["jmiller", "moko-deploy"],
|
||||
"push_whitelist_actions_user": true,
|
||||
"enable_force_push": false,
|
||||
"enable_force_push_allowlist": false,
|
||||
"force_push_allowlist_usernames": [],
|
||||
@@ -182,7 +188,8 @@ jobs:
|
||||
"rule_name": "alpha",
|
||||
"enable_push": true,
|
||||
"enable_push_whitelist": true,
|
||||
"push_whitelist_usernames": ["jmiller"],
|
||||
"push_whitelist_usernames": ["jmiller", "moko-deploy"],
|
||||
"push_whitelist_actions_user": true,
|
||||
"enable_force_push": false,
|
||||
"enable_force_push_allowlist": false,
|
||||
"force_push_allowlist_usernames": [],
|
||||
|
||||
@@ -1,66 +1,66 @@
|
||||
# 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"
|
||||
# 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
|
||||
MOKOGITEA_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"
|
||||
|
||||
@@ -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
|
||||
#
|
||||
# +=======================================================================+
|
||||
@@ -27,7 +27,7 @@ name: "Universal: Build & Release"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, closed]
|
||||
types: [opened, synchronize, closed]
|
||||
branches:
|
||||
- main
|
||||
paths-ignore:
|
||||
@@ -52,7 +52,7 @@ on:
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }}
|
||||
GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }}
|
||||
|
||||
@@ -64,9 +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_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
|
||||
@@ -74,6 +79,7 @@ jobs:
|
||||
with:
|
||||
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
fetch-depth: 1
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup mokocli tools
|
||||
env:
|
||||
@@ -101,7 +107,7 @@ jobs:
|
||||
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}" \
|
||||
--api-base "${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" \
|
||||
--pr "${{ github.event.pull_request.number }}"
|
||||
|
||||
- name: Checkout rc and configure git
|
||||
@@ -120,7 +126,7 @@ jobs:
|
||||
|
||||
- name: Update RC release notes from CHANGELOG.md
|
||||
run: |
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
|
||||
# Extract [Unreleased] section from changelog
|
||||
@@ -162,9 +168,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
|
||||
@@ -172,6 +182,7 @@ jobs:
|
||||
with:
|
||||
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
|
||||
- name: Configure git for bot pushes
|
||||
run: |
|
||||
@@ -268,7 +279,7 @@ jobs:
|
||||
!startsWith(steps.platform.outputs.platform, 'joomla')
|
||||
run: |
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
SEMVER_TAG="v${VERSION}"
|
||||
|
||||
@@ -293,7 +304,7 @@ jobs:
|
||||
|
||||
- name: Update release notes and promote changelog
|
||||
run: |
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
|
||||
# Get the stable release info (version and ID)
|
||||
@@ -362,7 +373,7 @@ 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="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
php ${MOKO_CLI}/release_mirror.php \
|
||||
--version "$VERSION" --tag "$RELEASE_TAG" \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
|
||||
@@ -391,7 +402,7 @@ jobs:
|
||||
if: steps.version.outputs.skip != 'true'
|
||||
continue-on-error: true
|
||||
run: |
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
|
||||
# Delete rc branch (ephemeral — created by promote-rc)
|
||||
@@ -415,7 +426,7 @@ jobs:
|
||||
if: steps.version.outputs.skip != 'true'
|
||||
continue-on-error: true
|
||||
run: |
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
API_BASE="${MOKOGITEA_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}"
|
||||
@@ -436,7 +447,7 @@ jobs:
|
||||
if: steps.version.outputs.skip != 'true'
|
||||
continue-on-error: true
|
||||
run: |
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
php ${MOKO_CLI}/version_reset_dev.php \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "${API_BASE}" \
|
||||
--branch dev --path . 2>&1 || true
|
||||
@@ -462,5 +473,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](${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/${{ steps.version.outputs.tag }}) |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Release | [View](${MOKOGITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/${{ steps.version.outputs.tag }}) |" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
@@ -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,13 +6,19 @@
|
||||
# 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)
|
||||
|
||||
name: "Generic: Project CI"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- dev
|
||||
- dev/**
|
||||
- rc/**
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
@@ -26,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
|
||||
@@ -124,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
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: mokocli.Universal
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
# PATH: /.mokogitea/workflows/ci-issue-reporter.yml
|
||||
# VERSION: 01.00.00
|
||||
# BRIEF: Reusable workflow — creates/updates a Gitea 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:
|
||||
MOKOGITEA_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:
|
||||
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
run: |
|
||||
MOKOGITEA_URL="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}"
|
||||
git clone --depth 1 --filter=blob:none --sparse "${MOKOGITEA_URL}/MokoConsulting/MokoCLI.git" /tmp/mokocli
|
||||
cd /tmp/mokocli && git sparse-checkout set cli/ci_issue_reporter.sh
|
||||
|
||||
- name: Report CI failure
|
||||
env:
|
||||
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
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 }}"
|
||||
@@ -115,7 +115,7 @@ jobs:
|
||||
|
||||
- name: "PHPCS (PSR-12)"
|
||||
run: |
|
||||
vendor/bin/phpcs --standard=phpcs.xml --report=summary --warning-severity=0 lib/ validate/ automation/ 2>&1 || {
|
||||
vendor/bin/phpcs --standard=phpcs.xml --report=summary --warning-severity=0 lib/ validate/ 2>&1 || {
|
||||
echo "::error::PHPCS found coding standard violations"
|
||||
echo "### PHPCS" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Coding standard violations detected. Run \`composer phpcs\` locally." >> $GITHUB_STEP_SUMMARY
|
||||
@@ -453,8 +453,8 @@ jobs:
|
||||
needs.governance.result == 'failure' ||
|
||||
needs.templates.result == 'failure')
|
||||
env:
|
||||
GITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
run: |
|
||||
chmod +x automation/ci-issue-reporter.sh
|
||||
REPORTER="./automation/ci-issue-reporter.sh"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -21,7 +21,7 @@ permissions:
|
||||
contents: write
|
||||
|
||||
env:
|
||||
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
MOKOGITEA_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.GA_TOKEN }}
|
||||
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
|
||||
- name: Delete merged branches
|
||||
env:
|
||||
GA_TOKEN: ${{ secrets.GA_TOKEN }}
|
||||
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
run: |
|
||||
echo "=== Merged Branch Cleanup ==="
|
||||
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
|
||||
API="${MOKOGITEA_URL}/api/v1/repos/${{ github.repository }}"
|
||||
|
||||
# List branches via API
|
||||
BRANCHES=$(curl -sS -H "Authorization: token ${GA_TOKEN}" \
|
||||
BRANCHES=$(curl -sS -H "Authorization: token ${MOKOGITEA_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 ${GA_TOKEN}" \
|
||||
curl -sS -X DELETE -H "Authorization: token ${MOKOGITEA_TOKEN}" \
|
||||
"${API}/branches/${BRANCH}" 2>/dev/null || true
|
||||
DELETED=$((DELETED + 1))
|
||||
fi
|
||||
@@ -66,20 +66,20 @@ jobs:
|
||||
|
||||
- name: Clean old workflow runs
|
||||
env:
|
||||
GA_TOKEN: ${{ secrets.GA_TOKEN }}
|
||||
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
run: |
|
||||
echo "=== Workflow Run Cleanup ==="
|
||||
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
|
||||
API="${MOKOGITEA_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 ${GA_TOKEN}" \
|
||||
RUNS=$(curl -sS -H "Authorization: token ${MOKOGITEA_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 ${GA_TOKEN}" \
|
||||
curl -sS -X DELETE -H "Authorization: token ${MOKOGITEA_TOKEN}" \
|
||||
"${API}/actions/runs/${RUN_ID}" 2>/dev/null || true
|
||||
DELETED=$((DELETED + 1))
|
||||
done
|
||||
|
||||
@@ -13,7 +13,7 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
@@ -49,18 +49,18 @@ jobs:
|
||||
- name: Verify Gitea registry
|
||||
run: |
|
||||
echo "Gitea Composer registry auto-publishes from tags."
|
||||
echo "Package available at: ${GITEA_URL}/api/packages/MokoConsulting/composer"
|
||||
echo "Package available at: ${MOKOGITEA_URL}/api/packages/MokoConsulting/composer"
|
||||
echo "Install: composer require mokoconsulting/mokocli"
|
||||
|
||||
# Packagist — notify of new version
|
||||
# Packagist — notify of new version (points to GitHub mirror which Packagist can access)
|
||||
- name: Notify Packagist
|
||||
if: secrets.PACKAGIST_TOKEN != ''
|
||||
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"}}' \
|
||||
-d '{"repository":{"url":"https://github.com/mokoconsulting-tech/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)"
|
||||
|
||||
@@ -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:
|
||||
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
|
||||
@@ -5,7 +5,7 @@
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: mokocli.Automation
|
||||
# VERSION: 09.39.00
|
||||
# VERSION: 09.42.00
|
||||
# BRIEF: Auto-create feature branch when an issue is opened
|
||||
|
||||
name: "Universal: Issue Branch"
|
||||
@@ -19,7 +19,7 @@ permissions:
|
||||
issues: write
|
||||
|
||||
env:
|
||||
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
MOKOGITEA_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.GA_TOKEN }}"
|
||||
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
|
||||
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
API="${MOKOGITEA_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="${GITEA_URL}/${{ github.repository }}"
|
||||
REPO_URL="${MOKOGITEA_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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+528
-534
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@
|
||||
# INGROUP: mokocli.Release
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
# PATH: /templates/workflows/universal/pre-release.yml.template
|
||||
# VERSION: 05.01.00
|
||||
# VERSION: 05.02.00
|
||||
# BRIEF: Auto pre-release on push to dev/alpha/beta/rc branches
|
||||
|
||||
name: "Universal: Pre-Release"
|
||||
@@ -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
|
||||
@@ -59,6 +63,11 @@ jobs:
|
||||
fetch-depth: 0
|
||||
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:
|
||||
|
||||
@@ -29,12 +29,20 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Rename branch
|
||||
env:
|
||||
BRANCH: ${{ github.event.pull_request.head.ref }}
|
||||
REPO: ${{ github.repository }}
|
||||
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
run: |
|
||||
BRANCH="${{ github.event.pull_request.head.ref }}"
|
||||
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
|
||||
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 }}"
|
||||
API="${GITEA_URL}/api/v1/repos/${REPO}/branches"
|
||||
|
||||
# Create dev/ branch from rc/ branch
|
||||
STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X POST \
|
||||
@@ -42,25 +50,22 @@ 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
|
||||
|
||||
# Delete rc/ branch
|
||||
ENCODED=$(php -r "echo rawurlencode('${BRANCH}');")
|
||||
# Read BRANCH from the environment inside PHP (getenv, no string interpolation -> no PHP injection)
|
||||
ENCODED=$(php -r 'echo rawurlencode(getenv("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
@@ -22,7 +22,7 @@ permissions:
|
||||
contents: write
|
||||
|
||||
env:
|
||||
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
|
||||
@@ -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 }}
|
||||
@@ -0,0 +1,130 @@
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow.Template
|
||||
# INGROUP: MokoStandards.CI
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Joomla
|
||||
# PATH: /.mokogitea/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.MOKOGITEA_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
|
||||
@@ -13,6 +13,7 @@
|
||||
name: "Universal: Workflow Sync Trigger"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
branches:
|
||||
@@ -26,8 +27,9 @@ jobs:
|
||||
name: Sync workflows to live repos
|
||||
runs-on: ubuntu-latest
|
||||
if: >-
|
||||
github.event.pull_request.merged == true &&
|
||||
!contains(github.event.pull_request.title, '[skip sync]')
|
||||
github.event_name == 'workflow_dispatch' ||
|
||||
(github.event.pull_request.merged == true &&
|
||||
!contains(github.event.pull_request.title, '[skip sync]'))
|
||||
|
||||
steps:
|
||||
- name: Determine platform from repo name
|
||||
@@ -49,8 +51,14 @@ jobs:
|
||||
env:
|
||||
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
run: |
|
||||
GITEA_URL="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}"
|
||||
git clone --depth 1 "${GITEA_URL}/MokoConsulting/mokocli.git" /tmp/mokocli
|
||||
MOKOGITEA_URL="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}"
|
||||
git clone --depth 1 "${MOKOGITEA_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
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
|
||||
+10
-5
@@ -12,12 +12,17 @@ BRIEF: Release changelog
|
||||
# Changelog
|
||||
## [Unreleased]
|
||||
|
||||
## [09.39.00] --- 2026-06-23
|
||||
## [09.42.00] --- 2026-07-04
|
||||
|
||||
## [09.38.00] --- 2026-06-21
|
||||
## [09.41.00] --- 2026-07-04
|
||||
|
||||
## [09.38.00] --- 2026-06-21
|
||||
## [09.41.00] --- 2026-07-04
|
||||
|
||||
## [09.38.00] --- 2026-06-21
|
||||
### Fixed
|
||||
- RecoverySuggestion.php: remove stray shebang and wrap an over-length line to satisfy PSR-12 (Gate 1 phpcs)
|
||||
- phpstan-baseline.neon: baseline pre-existing PHPStan level-6 findings across `cli/`, `lib/`, and `validate/` so Gate 1 static analysis passes (type-annotation debt tracked, not silently ignored)
|
||||
- client_provision.php: rename private `printSummary()` (and its dispatch entry) to `printProvisioningSummary()` to stop it colliding with `CliFramework::printSummary()` — a non-baselineable PHPStan override/covariance error
|
||||
|
||||
## [09.38.00] --- 2026-06-21
|
||||
## [09.41.00] --- 2026-07-04
|
||||
|
||||
## [09.41.00] --- 2026-07-04
|
||||
|
||||
@@ -6,7 +6,7 @@ DEFGROUP: MokoPlatform.Root
|
||||
INGROUP: MokoPlatform
|
||||
REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
PATH: /README.md
|
||||
VERSION: 09.39.00
|
||||
VERSION: 09.42.00
|
||||
BRIEF: Project overview and documentation
|
||||
-->
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/branch_rename.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Rename a git branch via Gitea API (create new, update PR, delete old)
|
||||
*/
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/bulk_workflow_push.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Push a workflow file to all governed repos via the Gitea Contents API
|
||||
*/
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/bulk_workflow_trigger.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Trigger a workflow across multiple repos at once
|
||||
*/
|
||||
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
#!/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: mokocli.CLI
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoCLI
|
||||
# PATH: /cli/ci_issue_reporter.sh
|
||||
# VERSION: 10.00.00
|
||||
# BRIEF: Creates or updates a Gitea issue when a CI gate fails.
|
||||
# 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 ────────────────────────────────────────────────────────────────
|
||||
MOKOGITEA_URL="${MOKOGITEA_URL:-https://git.mokoconsulting.tech}"
|
||||
MOKOGITEA_TOKEN="${MOKOGITEA_TOKEN:-}"
|
||||
REPO="${GITHUB_REPOSITORY:-}"
|
||||
RUN_URL="${GITHUB_SERVER_URL:-${MOKOGITEA_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: \$MOKOGITEA_TOKEN)
|
||||
--url Gitea base URL (default: \$MOKOGITEA_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) MOKOGITEA_TOKEN="$2"; shift 2 ;;
|
||||
--url) MOKOGITEA_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 "$MOKOGITEA_TOKEN" ]] && { echo "ERROR: MOKOGITEA_TOKEN not set"; exit 1; }
|
||||
[[ -z "$REPO" ]] && { echo "ERROR: GITHUB_REPOSITORY not set"; exit 1; }
|
||||
|
||||
API="${MOKOGITEA_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 ${MOKOGITEA_TOKEN}" \
|
||||
"${API}/labels" 2>/dev/null || echo "000")
|
||||
|
||||
if [[ "$exists" == "200" ]]; then
|
||||
local found
|
||||
found=$(curl -sf \
|
||||
-H "Authorization: token ${MOKOGITEA_TOKEN}" \
|
||||
"${API}/labels" 2>/dev/null \
|
||||
| grep -o "\"name\":\"${LABEL_NAME}\"" || true)
|
||||
|
||||
if [[ -z "$found" ]]; then
|
||||
curl -sf -X POST \
|
||||
-H "Authorization: token ${MOKOGITEA_TOKEN}" \
|
||||
-H "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() {
|
||||
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 ${MOKOGITEA_TOKEN}" \
|
||||
"${API}/issues?type=issues&state=open&labels=${LABEL_NAME}&q=${query}&limit=5" \
|
||||
2>/dev/null || echo "[]")
|
||||
|
||||
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](${MOKOGITEA_URL}/MokoConsulting/MokoCLI/src/branch/main/cli/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
|
||||
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 ${MOKOGITEA_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
|
||||
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)
|
||||
|
||||
RESPONSE=$(curl -sf -X POST \
|
||||
-H "Authorization: token ${MOKOGITEA_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
|
||||
LABEL_ID=$(curl -sf \
|
||||
-H "Authorization: token ${MOKOGITEA_TOKEN}" \
|
||||
"${API}/labels" 2>/dev/null \
|
||||
| grep -oP "\"id\":\s*\K[0-9]+(?=[^}]*\"name\":\s*\"${LABEL_NAME}\")" \
|
||||
| head -1 || true)
|
||||
|
||||
if [[ -n "$LABEL_ID" ]]; then
|
||||
curl -sf -X POST \
|
||||
-H "Authorization: token ${MOKOGITEA_TOKEN}" \
|
||||
-H "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
|
||||
@@ -12,7 +12,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/client_dashboard.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Generate unified client dashboard HTML
|
||||
*/
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/client_inventory.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Discover and list all client-waas repos with their server configuration status
|
||||
*/
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/client_provision.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Provision a new client environment end-to-end
|
||||
*/
|
||||
|
||||
@@ -104,7 +104,7 @@ class ClientProvisionCli extends CliFramework
|
||||
'variables' => 'setVariables',
|
||||
'secrets' => 'setSecrets',
|
||||
'monitoring' => 'setupMonitoring',
|
||||
'summary' => 'printSummary',
|
||||
'summary' => 'printProvisioningSummary',
|
||||
];
|
||||
|
||||
$exitCode = 0;
|
||||
@@ -383,7 +383,7 @@ class ClientProvisionCli extends CliFramework
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function printSummary(): int
|
||||
private function printProvisioningSummary(): int
|
||||
{
|
||||
$vars = $this->config['variables'] ?? [];
|
||||
$secrets = $this->config['secrets'] ?? [];
|
||||
|
||||
@@ -95,6 +95,10 @@ class CreateProjectCli extends CliFramework
|
||||
|
||||
$repoRoot = dirname(__DIR__, 2);
|
||||
$templatesDir = "{$repoRoot}/templates/projects";
|
||||
if (!is_dir($templatesDir)) {
|
||||
$this->log('ERROR', "Project templates directory not found: {$templatesDir}");
|
||||
return 1;
|
||||
}
|
||||
|
||||
$repos = [];
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/grafana_dashboard.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Manage Grafana dashboards via API
|
||||
*/
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/joomla_build.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Build a Joomla extension ZIP from manifest — all types supported
|
||||
* NOTE: Called by pre-release and auto-release workflows.
|
||||
*/
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/joomla_metadata_validate.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Validate MokoGitea repo metadata against Joomla extension manifest XML
|
||||
*/
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/manifest_detect.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Auto-detect manifest fields from source files and optionally push to API
|
||||
*/
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/manifest_integrity.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Cross-check manifest API fields against repo contents across the org
|
||||
*/
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/manifest_licensing.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Ensure licensing tags (updateservers, dlid) in Joomla extension manifests
|
||||
*/
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/manifest_read.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Read repo metadata from Gitea manifest API, auto-detect the rest
|
||||
*/
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/platform_detect.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Auto-detect repository platform type and optionally update manifest
|
||||
*/
|
||||
|
||||
|
||||
+1
-14
@@ -40,7 +40,6 @@ class ReleaseCli extends CliFramework
|
||||
$bulkSyncFile = file_exists("{$repoRoot}/.mokogitea/workflows/bulk-repo-sync.yml")
|
||||
? "{$repoRoot}/.mokogitea/workflows/bulk-repo-sync.yml"
|
||||
: "{$repoRoot}/.github/workflows/bulk-repo-sync.yml";
|
||||
$cleanupFile = "{$repoRoot}/templates/workflows/shared/repository-cleanup.yml.template";
|
||||
|
||||
// -- Step 1: Read current version --
|
||||
$readme = "{$repoRoot}/README.md";
|
||||
@@ -131,19 +130,7 @@ class ReleaseCli extends CliFramework
|
||||
file_put_contents($bulkSyncFile, $bulkContent);
|
||||
}
|
||||
|
||||
// -- Step 5: Update repository-cleanup.yml current branch --
|
||||
echo "Updating repository-cleanup.yml -> chore/sync-mokostandards-v{$minorVersion}\n";
|
||||
if (!$this->dryRun) {
|
||||
$cleanupContent = file_get_contents($cleanupFile);
|
||||
$cleanupContent = preg_replace(
|
||||
'/CURRENT="chore\/sync-mokostandards-v[^"]*"/',
|
||||
"CURRENT=\"chore/sync-mokostandards-v{$minorVersion}\"",
|
||||
$cleanupContent
|
||||
);
|
||||
file_put_contents($cleanupFile, $cleanupContent);
|
||||
}
|
||||
|
||||
// -- Step 6: Commit changes --
|
||||
// -- Step 5: Commit changes --
|
||||
if (!$this->dryRun) {
|
||||
echo "Committing...\n";
|
||||
passthru("cd {$repoRoot} && git add -A && git commit -m \"chore(release): prepare {$currentVersion} release [skip ci]\"");
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/release_cascade.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Cascade release zip to all lower stability channels
|
||||
*/
|
||||
|
||||
|
||||
+79
-1
@@ -270,12 +270,90 @@ class ReleasePackageCli extends CliFramework
|
||||
}
|
||||
}
|
||||
|
||||
// Check if sub-source is itself a Joomla package (nested package)
|
||||
$nestedPkgManifests = glob("{$subSourceDir}/pkg_*.xml") ?: [];
|
||||
$isNestedPackage = !empty($nestedPkgManifests) && is_dir("{$subSourceDir}/packages");
|
||||
|
||||
$subZip = new \ZipArchive();
|
||||
if ($subZip->open($subZipPath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE) !== true) {
|
||||
$this->log('ERROR', "Failed to create sub-package ZIP: {$subZipPath}");
|
||||
continue;
|
||||
}
|
||||
$this->addDirToZip($subZip, $subSourceDir, '', $this->excludePatterns);
|
||||
|
||||
if ($isNestedPackage) {
|
||||
// Build nested package: zip each sub-extension, then assemble
|
||||
echo " Building nested package: {$subName}\n";
|
||||
$nestedPkgDirs = glob("{$subSourceDir}/packages/*", GLOB_ONLYDIR) ?: [];
|
||||
|
||||
$nestedManifested = [];
|
||||
foreach ($nestedPkgManifests as $npmf) {
|
||||
$npmXml = @simplexml_load_file($npmf);
|
||||
if ($npmXml && isset($npmXml->files)) {
|
||||
foreach ($npmXml->files->file as $fn) {
|
||||
$nzn = pathinfo((string) $fn, PATHINFO_FILENAME);
|
||||
if (!empty($nzn)) {
|
||||
$nestedManifested[$nzn] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use a subdirectory to avoid filename collisions with outer ZIPs
|
||||
$nestedOutputDir = "{$outputDir}/nested_{$subName}";
|
||||
@mkdir($nestedOutputDir, 0755, true);
|
||||
|
||||
foreach ($nestedPkgDirs as $npd) {
|
||||
$nestedSubName = basename($npd);
|
||||
if (!empty($nestedManifested) && !isset($nestedManifested[$nestedSubName])) {
|
||||
continue;
|
||||
}
|
||||
$nestedSubZipPath = "{$nestedOutputDir}/{$nestedSubName}.zip";
|
||||
$nsZip = new \ZipArchive();
|
||||
if ($nsZip->open($nestedSubZipPath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE) !== true) {
|
||||
continue;
|
||||
}
|
||||
$this->addDirToZip($nsZip, $npd, '', $this->excludePatterns);
|
||||
$nsZip->close();
|
||||
$subZip->addFile($nestedSubZipPath, "packages/{$nestedSubName}.zip");
|
||||
echo " Nested sub: {$nestedSubName}.zip\n";
|
||||
}
|
||||
|
||||
// Patch nested manifest: ensure folder="packages" so Joomla finds sub-ZIPs
|
||||
foreach ($nestedPkgManifests as $npmf) {
|
||||
$npmContent = file_get_contents($npmf);
|
||||
if ($npmContent !== false
|
||||
&& strpos($npmContent, '<files>') !== false
|
||||
&& strpos($npmContent, 'folder="packages"') === false
|
||||
) {
|
||||
$npmContent = str_replace('<files>', '<files folder="packages">', $npmContent);
|
||||
file_put_contents($npmf, $npmContent);
|
||||
echo " Fixed: added folder=\"packages\" to " . basename($npmf) . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Add top-level files (manifest, script, etc.) with exclude filter
|
||||
$nestedTopFiles = array_merge(
|
||||
glob("{$subSourceDir}/*.xml") ?: [],
|
||||
glob("{$subSourceDir}/*.php") ?: []
|
||||
);
|
||||
foreach ($nestedTopFiles as $ntf) {
|
||||
if (!$this->isExcluded(basename($ntf), $this->excludePatterns)) {
|
||||
$subZip->addFile($ntf, basename($ntf));
|
||||
}
|
||||
}
|
||||
|
||||
// Add all top-level directories except packages/
|
||||
$nestedTopDirs = glob("{$subSourceDir}/*", GLOB_ONLYDIR) ?: [];
|
||||
foreach ($nestedTopDirs as $ntd) {
|
||||
$ndName = basename($ntd);
|
||||
if ($ndName === 'packages') {
|
||||
continue;
|
||||
}
|
||||
$this->addDirToZip($subZip, $ntd, $ndName, $this->excludePatterns);
|
||||
}
|
||||
} else {
|
||||
$this->addDirToZip($subZip, $subSourceDir, '', $this->excludePatterns);
|
||||
}
|
||||
$subZip->close();
|
||||
|
||||
$zip->addFile($subZipPath, "packages/{$subName}.zip");
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/release_publish.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Publish a release and create copies for all lesser stability streams.
|
||||
*/
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/scaffold_client.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Scaffold a new client-waas repo from Template-Client-WaaS with pre-configured settings
|
||||
*/
|
||||
|
||||
|
||||
@@ -0,0 +1,294 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* FILE INFORMATION
|
||||
* DEFGROUP: mokocli.CLI
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/theme_vars_check.php
|
||||
* BRIEF: Validate a client MokoOnyx theme package — required CSS variables
|
||||
* (derived dynamically from the MokoOnyx standard theme) are defined in
|
||||
* the client's light/dark custom CSS, required files exist, the manifest
|
||||
* is sane, and (optionally) the repo's Gitea metadata is set.
|
||||
*
|
||||
* Standalone (no CliFramework dependency) so it runs even when the shared
|
||||
* framework autoloader is unavailable.
|
||||
*
|
||||
* Usage:
|
||||
* php theme_vars_check.php --path . --reference /tmp/mokoonyx [--github-output]
|
||||
* [--api-base <url> --repo <owner/repo> --token <token>]
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
$opts = getopt('', ['path:', 'reference:', 'github-output', 'api-base:', 'repo:', 'token:']);
|
||||
$path = isset($opts['path']) && is_string($opts['path']) && $opts['path'] !== '' ? $opts['path'] : '.';
|
||||
$ref = isset($opts['reference']) && is_string($opts['reference']) ? $opts['reference'] : '';
|
||||
$gh = array_key_exists('github-output', $opts);
|
||||
|
||||
$root = realpath($path);
|
||||
if ($root === false) { $root = $path; }
|
||||
|
||||
$src = is_dir("$root/src") ? "$root/src" : (is_dir("$root/source") ? "$root/source" : null);
|
||||
if ($src === null) {
|
||||
fwrite(STDERR, "ERROR: no src/ or source/ directory under $root\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$errors = 0;
|
||||
$summary = [];
|
||||
$fail = function (string $msg) use (&$errors, &$summary): void {
|
||||
echo " [FAIL] $msg\n";
|
||||
$summary[] = "FAIL: $msg";
|
||||
$errors++;
|
||||
};
|
||||
$ok = function (string $msg): void { echo " [ok] $msg\n"; };
|
||||
$note = function (string $msg): void { echo " [note] $msg\n"; };
|
||||
|
||||
/** Extract the set of CSS custom-property names DEFINED in a CSS string. */
|
||||
$definedVars = static function (string $css): array {
|
||||
// Matches "--name:" at a declaration position (not var(--name) uses).
|
||||
preg_match_all('/(?:^|[\s;{])(--[a-z0-9_-]+)\s*:/i', $css, $m);
|
||||
return array_values(array_unique(array_map('strtolower', $m[1] ?? [])));
|
||||
};
|
||||
|
||||
/** Find the MokoOnyx standard theme file for a mode inside a reference checkout. */
|
||||
$findStandard = static function (string $ref, string $mode): ?string {
|
||||
if ($ref === '') { return null; }
|
||||
foreach ([
|
||||
"$ref/source/media/css/theme/$mode.standard.css",
|
||||
"$ref/media/templates/site/mokoonyx/css/theme/$mode.standard.css",
|
||||
"$ref/$mode.standard.css",
|
||||
] as $cand) {
|
||||
if (is_file($cand)) { return $cand; }
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
$cssDir = "$src/media/templates/site/mokoonyx/css";
|
||||
$themeDir = "$cssDir/theme";
|
||||
$manifest = "$src/templateDetails.xml";
|
||||
$customs = ['light' => "$themeDir/light.custom.css", 'dark' => "$themeDir/dark.custom.css"];
|
||||
|
||||
echo "MokoOnyx theme validation: $src\n\n";
|
||||
|
||||
// 1) Required files -------------------------------------------------------
|
||||
echo "=== Required files ===\n";
|
||||
$requiredFiles = [
|
||||
'templateDetails.xml' => $manifest,
|
||||
'theme/light.custom.css' => $customs['light'],
|
||||
'theme/dark.custom.css' => $customs['dark'],
|
||||
'user.css' => "$cssDir/user.css",
|
||||
];
|
||||
foreach ($requiredFiles as $label => $file) {
|
||||
is_file($file) ? $ok("$label present") : $fail("missing required file: $label");
|
||||
}
|
||||
|
||||
// 1b) Forbidden committed files ------------------------------------------
|
||||
echo "\n=== Forbidden files ===\n";
|
||||
$scan = static function (string $dir, array $skip) use (&$scan): array {
|
||||
$out = [];
|
||||
foreach (scandir($dir) ?: [] as $e) {
|
||||
if ($e === '.' || $e === '..') { continue; }
|
||||
$p = "$dir/$e";
|
||||
if (is_dir($p)) {
|
||||
if (in_array($e, $skip, true)) { continue; }
|
||||
$out = array_merge($out, $scan($p, $skip));
|
||||
} else {
|
||||
$out[] = $p;
|
||||
}
|
||||
}
|
||||
return $out;
|
||||
};
|
||||
$forbidden = [];
|
||||
if (is_dir("$root/.claude")) { $forbidden[] = '.claude/'; }
|
||||
foreach ($scan($root, ['.git', 'vendor', 'node_modules']) as $f) {
|
||||
$b = basename($f);
|
||||
$rel = ltrim(str_replace('\\', '/', substr($f, strlen($root))), '/');
|
||||
if ($b === '.mcp.json' || $b === 'TODO.md'
|
||||
|| fnmatch('.mcp_*.json', $b) || fnmatch('sftp-config*.json', $b)
|
||||
|| fnmatch('*.min.css', $b) || fnmatch('*.min.js', $b)) {
|
||||
$forbidden[] = $rel;
|
||||
}
|
||||
}
|
||||
$forbidden = array_values(array_unique($forbidden));
|
||||
if ($forbidden) {
|
||||
$shown = array_slice($forbidden, 0, 10);
|
||||
$more = count($forbidden) - count($shown);
|
||||
$fail('forbidden file(s) committed: ' . implode(', ', $shown) . ($more > 0 ? " (+$more more)" : ''));
|
||||
} else {
|
||||
$ok('no forbidden files committed');
|
||||
}
|
||||
|
||||
// 2) CSS variables — required set derived from the MokoOnyx standard theme
|
||||
echo "\n=== CSS variables vs MokoOnyx standard theme ===\n";
|
||||
if ($ref === '') {
|
||||
$note('no --reference given; skipping variable parity check');
|
||||
} else {
|
||||
foreach ($customs as $mode => $customFile) {
|
||||
$std = $findStandard($ref, $mode);
|
||||
if ($std === null) {
|
||||
$fail("$mode: standard theme not found under reference '$ref'");
|
||||
continue;
|
||||
}
|
||||
if (!is_file($customFile)) {
|
||||
continue; // already reported missing
|
||||
}
|
||||
$required = $definedVars((string) file_get_contents($std));
|
||||
$defined = $definedVars((string) file_get_contents($customFile));
|
||||
$missing = array_values(array_diff($required, $defined));
|
||||
if ($missing) {
|
||||
$shown = array_slice($missing, 0, 15);
|
||||
$more = count($missing) - count($shown);
|
||||
$fail("$mode mode missing " . count($missing) . '/' . count($required)
|
||||
. ' standard variable(s): ' . implode(', ', $shown) . ($more > 0 ? " (+$more more)" : ''));
|
||||
} else {
|
||||
$ok("$mode mode defines all " . count($required) . ' standard variables');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3) Manifest sanity ------------------------------------------------------
|
||||
echo "\n=== Manifest (templateDetails.xml) ===\n";
|
||||
if (is_file($manifest)) {
|
||||
$xml = @simplexml_load_file($manifest);
|
||||
if ($xml === false) {
|
||||
$fail('templateDetails.xml is not well-formed XML');
|
||||
} else {
|
||||
$version = isset($xml->version) ? trim((string) $xml->version) : '';
|
||||
$version !== '' ? $ok("version $version") : $fail('<version> is missing or empty');
|
||||
|
||||
$server = isset($xml->updateservers->server) ? trim((string) $xml->updateservers->server) : '';
|
||||
if ($server === '') {
|
||||
$fail('<updateservers><server> is missing');
|
||||
} elseif (strpos($server, '/raw/branch/') !== false) {
|
||||
$fail('update server uses a legacy raw/branch URL; use the dynamic MokoGitea feed');
|
||||
} else {
|
||||
$ok("update server: $server");
|
||||
}
|
||||
|
||||
isset($xml->dlid) ? $ok('<dlid> license-key field present')
|
||||
: $fail('<dlid prefix="dlid=" suffix=""/> is missing');
|
||||
|
||||
// Element naming convention (MokoOnyx client theme file package)
|
||||
$type = trim((string) ($xml['type'] ?? ''));
|
||||
$element = isset($xml->element) ? trim((string) $xml->element) : '';
|
||||
if ($type === 'file' && $element !== '') {
|
||||
strpos($element, 'file_mokoonyx_') === 0
|
||||
? $ok("element naming ok ($element)")
|
||||
: $fail("element '$element' should start with 'file_mokoonyx_' for a MokoOnyx client theme package");
|
||||
}
|
||||
|
||||
// Required manifest fields
|
||||
foreach (['name', 'element', 'author', 'creationDate'] as $field) {
|
||||
(isset($xml->$field) && trim((string) $xml->$field) !== '')
|
||||
? $ok("<$field> present")
|
||||
: $fail("<$field> is missing or empty");
|
||||
}
|
||||
|
||||
// scriptfile (if declared) must exist
|
||||
if (isset($xml->scriptfile)) {
|
||||
$sf = trim((string) $xml->scriptfile);
|
||||
is_file("$src/$sf") ? $ok("scriptfile '$sf' present")
|
||||
: $fail("<scriptfile> references '$sf' which is not in src/");
|
||||
}
|
||||
|
||||
// Fileset integrity — every referenced file/folder must exist in src/
|
||||
if (isset($xml->fileset)) {
|
||||
$missingFs = [];
|
||||
foreach ($xml->fileset->files as $files) {
|
||||
$folder = trim((string) ($files['folder'] ?? ''));
|
||||
$baseDir = $folder !== '' ? "$src/$folder" : $src;
|
||||
foreach ($files->filename as $fn) {
|
||||
$rel = ($folder !== '' ? "$folder/" : '') . trim((string) $fn);
|
||||
if (!is_file("$baseDir/" . trim((string) $fn))) { $missingFs[] = $rel; }
|
||||
}
|
||||
foreach ($files->folder as $fd) {
|
||||
$rel = ($folder !== '' ? "$folder/" : '') . trim((string) $fd) . '/';
|
||||
if (!is_dir("$baseDir/" . trim((string) $fd))) { $missingFs[] = $rel; }
|
||||
}
|
||||
}
|
||||
if ($missingFs) {
|
||||
$shown = array_slice($missingFs, 0, 10);
|
||||
$more = count($missingFs) - count($shown);
|
||||
$fail('fileset references ' . count($missingFs) . ' missing path(s): '
|
||||
. implode(', ', $shown) . ($more > 0 ? " (+$more more)" : ''));
|
||||
} else {
|
||||
$ok('all fileset paths exist in src/');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4) Repository metadata via Gitea API (optional) -------------------------
|
||||
$apiBase = isset($opts['api-base']) && is_string($opts['api-base']) ? rtrim($opts['api-base'], '/') : '';
|
||||
$repoSlug = isset($opts['repo']) && is_string($opts['repo']) ? trim($opts['repo']) : '';
|
||||
$token = isset($opts['token']) && is_string($opts['token']) ? trim($opts['token']) : '';
|
||||
if ($apiBase !== '' && $repoSlug !== '' && $token !== '') {
|
||||
echo "\n=== Repository metadata (Gitea API) ===\n";
|
||||
$url = "$apiBase/repos/$repoSlug";
|
||||
$ctx = stream_context_create(['http' => [
|
||||
'method' => 'GET',
|
||||
'header' => "Authorization: token $token\r\nAccept: application/json\r\n",
|
||||
'ignore_errors' => true,
|
||||
'timeout' => 15,
|
||||
]]);
|
||||
$resp = @file_get_contents($url, false, $ctx);
|
||||
$data = $resp !== false ? json_decode($resp, true) : null;
|
||||
if (!is_array($data) || !isset($data['name'])) {
|
||||
$fail("could not read repo metadata from Gitea API ($url)");
|
||||
} else {
|
||||
trim((string) ($data['description'] ?? '')) !== '' ? $ok('description set')
|
||||
: $fail('repo description is empty');
|
||||
trim((string) ($data['website'] ?? '')) !== '' ? $ok('website set: ' . $data['website'])
|
||||
: $fail('repo website is empty');
|
||||
$topics = $data['topics'] ?? [];
|
||||
(is_array($topics) && count($topics) > 0) ? $ok(count($topics) . ' topic(s) set')
|
||||
: $fail('repo has no topics');
|
||||
|
||||
// Required topics
|
||||
$requiredTopics = ['joomla', 'client-waas', 'mokoonyx'];
|
||||
$haveTopics = array_map('strtolower', is_array($topics) ? $topics : []);
|
||||
$missingTopics = array_values(array_diff($requiredTopics, $haveTopics));
|
||||
$missingTopics
|
||||
? $fail('missing required topic(s): ' . implode(', ', $missingTopics))
|
||||
: $ok('required topics present (' . implode(', ', $requiredTopics) . ')');
|
||||
|
||||
((string) ($data['default_branch'] ?? '')) === 'main' ? $ok('default branch is main')
|
||||
: $fail("default branch is '" . ($data['default_branch'] ?? '') . "' (expected main)");
|
||||
|
||||
// Branch protection on main
|
||||
$bresp = @file_get_contents("$apiBase/repos/$repoSlug/branches/main", false, $ctx);
|
||||
$bdata = $bresp !== false ? json_decode($bresp, true) : null;
|
||||
if (is_array($bdata) && array_key_exists('protected', $bdata)) {
|
||||
$bdata['protected'] ? $ok('main branch is protected')
|
||||
: $fail('main branch is not protected');
|
||||
} else {
|
||||
$note('could not read branch protection state for main');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo "\n=== Repository metadata (Gitea API) ===\n";
|
||||
$note('API args not provided; skipping repo metadata check');
|
||||
}
|
||||
|
||||
// Output / exit -----------------------------------------------------------
|
||||
echo "\n";
|
||||
if ($gh && ($f = getenv('GITHUB_STEP_SUMMARY'))) {
|
||||
$md = "## MokoOnyx Theme Validation\n\n";
|
||||
$md .= $errors === 0
|
||||
? "All checks passed.\n"
|
||||
: implode("\n", array_map(static fn ($l) => "- $l", $summary)) . "\n";
|
||||
@file_put_contents($f, $md, FILE_APPEND);
|
||||
}
|
||||
|
||||
if ($errors > 0) {
|
||||
echo "FAILED: $errors issue(s) found.\n";
|
||||
exit(1);
|
||||
}
|
||||
echo "All MokoOnyx theme validation checks passed.\n";
|
||||
exit(0);
|
||||
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/updates_xml_sync.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Sync updates.xml to target branches via Gitea API
|
||||
* NOTE: Called by pre-release and auto-release workflows after updates.xml
|
||||
* is modified on the current branch. Pushes the file to other branches
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/version_auto_bump.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Auto patch-bump, set stability suffix, and commit — single CLI replacing inline workflow bash
|
||||
*/
|
||||
|
||||
|
||||
+22
-3
@@ -214,7 +214,8 @@ class VersionBumpCli extends CliFramework
|
||||
$newContent = preg_replace(
|
||||
$xmlPattern,
|
||||
'${1}' . $newBase . '</version>',
|
||||
$content
|
||||
$content,
|
||||
1
|
||||
);
|
||||
} else {
|
||||
$xmlPattern = '#<version>\d{2}\.\d{2}\.\d{2}'
|
||||
@@ -222,9 +223,13 @@ class VersionBumpCli extends CliFramework
|
||||
$newContent = preg_replace(
|
||||
$xmlPattern,
|
||||
"<version>{$newFull}</version>",
|
||||
$content
|
||||
$content,
|
||||
1
|
||||
);
|
||||
}
|
||||
if ($newContent !== null) {
|
||||
$newContent = preg_replace('#(\s*<version>[^<]*</version>)\s*<version>[^<]*</version>#', '$1', $newContent);
|
||||
}
|
||||
if ($newContent !== null && $newContent !== $content) {
|
||||
file_put_contents($xmlFile, $newContent);
|
||||
$updatedFiles[] = substr($xmlFile, strlen($root) + 1);
|
||||
@@ -234,6 +239,20 @@ class VersionBumpCli extends CliFramework
|
||||
if (!empty($updatedFiles)) {
|
||||
fwrite(STDERR, "Updated " . count($updatedFiles) . " Joomla manifest(s): " . implode(', ', $updatedFiles) . "\n");
|
||||
}
|
||||
// Joomla schema version: create empty SQL update file if sql/updates/mysql/ exists
|
||||
$sqlUpdateDirs = array_merge(
|
||||
SourceResolver::globSource($root, 'packages/*/sql/updates/mysql'),
|
||||
SourceResolver::globSource($root, 'sql/updates/mysql'),
|
||||
glob("{$root}/sql/updates/mysql") ?: []
|
||||
);
|
||||
$sqlUpdateDirs = array_unique(array_filter($sqlUpdateDirs, 'is_dir'));
|
||||
foreach ($sqlUpdateDirs as $sqlDir) {
|
||||
$sqlFile = "{$sqlDir}/{$newBase}.sql";
|
||||
if (!file_exists($sqlFile)) {
|
||||
file_put_contents($sqlFile, "/* {$newBase} — no schema changes */\n");
|
||||
fwrite(STDERR, "Created SQL update file: " . substr($sqlFile, strlen($root) + 1) . "\n");
|
||||
}
|
||||
}
|
||||
$packageJsonFile = "{$root}/package.json";
|
||||
if (file_exists($packageJsonFile)) {
|
||||
$pkgContent = file_get_contents($packageJsonFile);
|
||||
@@ -370,7 +389,7 @@ class VersionBumpCli extends CliFramework
|
||||
/**
|
||||
* Scan git release tags for the highest version across all channels.
|
||||
*
|
||||
* Checks release names like "MokoSuiteClient (VERSION: 09.39.00)" in
|
||||
* Checks release names like "MokoSuiteClient (VERSION: 09.42.00)" in
|
||||
* git tags (stable, release-candidate, development, etc.) to find the
|
||||
* highest version that has been released on any channel.
|
||||
*/
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/version_check.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Validate version consistency across README, manifests, and sub-packages
|
||||
*/
|
||||
|
||||
@@ -131,9 +131,11 @@ class VersionCheckCli extends CliFramework
|
||||
$updated = preg_replace(
|
||||
$vPat,
|
||||
"<version>{$highestVersion}</version>",
|
||||
$content
|
||||
$content,
|
||||
1
|
||||
);
|
||||
if ($updated !== null) {
|
||||
$updated = preg_replace('#(\s*<version>[^<]*</version>)\s*<version>[^<]*</version>#', '$1', $updated);
|
||||
file_put_contents($mokoManifest, $updated);
|
||||
} echo " Fixed: .mokogitea/manifest.xml -> {$highestVersion}\n";
|
||||
}
|
||||
@@ -185,8 +187,9 @@ class VersionCheckCli extends CliFramework
|
||||
if (!file_exists($file)) {
|
||||
continue;
|
||||
} $content = file_get_contents($file);
|
||||
$updated = preg_replace('#<version>[^<]*</version>#', "<version>{$highestVersion}</version>", $content);
|
||||
$updated = preg_replace('#<version>[^<]*</version>#', "<version>{$highestVersion}</version>", $content, 1);
|
||||
if ($updated !== null) {
|
||||
$updated = preg_replace('#(\s*<version>[^<]*</version>)\s*<version>[^<]*</version>#', '$1', $updated);
|
||||
file_put_contents($file, $updated);
|
||||
} echo " Fixed: {$source} -> {$highestVersion}\n";
|
||||
}
|
||||
|
||||
@@ -164,8 +164,12 @@ class VersionSetPlatformCli extends CliFramework
|
||||
$updated = preg_replace(
|
||||
'|<version>[^<]*</version>|',
|
||||
"<version>{$version}</version>",
|
||||
$content
|
||||
$content,
|
||||
1
|
||||
);
|
||||
if ($updated !== null) {
|
||||
$updated = preg_replace('#(\s*<version>[^<]*</version>)\s*<version>[^<]*</version>#', '$1', $updated);
|
||||
}
|
||||
if ($updated !== null && $updated !== $content) {
|
||||
file_put_contents($file, $updated);
|
||||
$relPath = str_replace($root . '/', '', $file);
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/wiki_sync.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Sync select wiki pages from mokocli to all template repos
|
||||
*/
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* INGROUP: mokocli
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /cli/workflow_sync.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Sync workflows from Generic → platform templates → live repos based on manifest.platform
|
||||
*/
|
||||
|
||||
|
||||
+2
-2
@@ -71,8 +71,8 @@
|
||||
],
|
||||
"scripts": {
|
||||
"test": "phpunit",
|
||||
"phpcs": "phpcs --standard=phpcs.xml lib/ validate/ automation/",
|
||||
"phpstan": "phpstan analyse -c phpstan.neon lib/ validate/ automation/",
|
||||
"phpcs": "phpcs --standard=phpcs.xml lib/ validate/",
|
||||
"phpstan": "phpstan analyse -c phpstan.neon lib/ validate/",
|
||||
"psalm": "psalm --config=psalm.xml",
|
||||
"check": [
|
||||
"@phpcs",
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* INGROUP: MokoPlatform
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /deploy/backup-before-deploy.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Snapshot Joomla directories before deployment for rollback capability
|
||||
*/
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* INGROUP: MokoPlatform
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /deploy/deploy-dolibarr.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Deploy Dolibarr module files to a remote server via SFTP/rsync
|
||||
*/
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* INGROUP: MokoPlatform
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /deploy/health-check.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Post-deploy health check — verify a Joomla site is responding correctly
|
||||
*/
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* INGROUP: MokoPlatform
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /deploy/rollback-joomla.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Rollback a Joomla deployment by restoring from a pre-deploy snapshot
|
||||
*/
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* INGROUP: MokoPlatform
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
* PATH: /deploy/sync-joomla.php
|
||||
* VERSION: 09.39.00
|
||||
* VERSION: 09.42.00
|
||||
* BRIEF: Sync Joomla site directories between two servers via rsync over SSH
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
@@ -76,7 +75,9 @@ class RecoverySuggestion
|
||||
*/
|
||||
public static function forMissingHeader(string $file): string
|
||||
{
|
||||
return "Add SPDX license header to {$file}:\n /* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>\n * SPDX-License-Identifier: GPL-3.0-or-later */";
|
||||
return "Add SPDX license header to {$file}:\n"
|
||||
. " /* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>\n"
|
||||
. " * SPDX-License-Identifier: GPL-3.0-or-later */";
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -930,10 +930,10 @@ class RepositorySynchronizer
|
||||
private const TEMPLATE_REPOS = [
|
||||
'joomla' => 'MokoConsulting/Template-Joomla',
|
||||
'waas-component' => 'MokoConsulting/Template-Joomla',
|
||||
'dolibarr' => 'MokoConsulting/Template-Dolibarr',
|
||||
'crm-module' => 'MokoConsulting/Template-Dolibarr',
|
||||
'generic' => 'MokoConsulting/Template-Generic',
|
||||
'mcp' => 'MokoConsulting/Template-Generic',
|
||||
'dolibarr' => 'MokoConsulting/Template-Generic',
|
||||
'crm-module' => 'MokoConsulting/Template-Generic',
|
||||
'client' => 'MokoConsulting/Template-Client-WaaS',
|
||||
];
|
||||
|
||||
@@ -951,7 +951,6 @@ class RepositorySynchronizer
|
||||
*/
|
||||
private const TEMPLATE_SYNC_TARGETS = [
|
||||
'MokoConsulting/Template-Joomla',
|
||||
'MokoConsulting/Template-Dolibarr',
|
||||
'MokoConsulting/Template-Client-WaaS',
|
||||
];
|
||||
|
||||
@@ -1083,20 +1082,6 @@ class RepositorySynchronizer
|
||||
}
|
||||
}
|
||||
|
||||
// CODEOWNERS — GitHub only; Gitea doesn't enforce it
|
||||
if ($this->adapter->getPlatformName() === 'github') {
|
||||
$shared[] = ['templates/mokogitea/CODEOWNERS', '.github/CODEOWNERS'];
|
||||
}
|
||||
|
||||
// Platform-specific gitignore (merged, not replaced)
|
||||
$gitignoreMap = [
|
||||
'dolibarr' => 'templates/configs/gitignore.dolibarr',
|
||||
'platform' => 'templates/configs/gitignore.dolibarr',
|
||||
'joomla' => 'templates/configs/.gitignore.joomla',
|
||||
];
|
||||
$gitignoreTemplate = $gitignoreMap[$platform] ?? 'templates/configs/gitignore';
|
||||
$shared[] = [$gitignoreTemplate, '.gitignore'];
|
||||
|
||||
// Create TODO.md stub if it doesn't exist (gitignored after first commit)
|
||||
$entries[] = [
|
||||
'inline_content' => "# TODO\n\n> **Note:** This file is not tracked in "
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
DEFGROUP: dolibarr-api-mcp.Documentation
|
||||
INGROUP: dolibarr-api-mcp
|
||||
REPO: https://git.mokoconsulting.tech/MokoConsulting/dolibarr-api-mcp
|
||||
VERSION: 09.39.00
|
||||
VERSION: 09.42.00
|
||||
PATH: ./CONTRIBUTING.md
|
||||
BRIEF: Contribution guidelines for the project
|
||||
-->
|
||||
|
||||
@@ -10,7 +10,7 @@ DEFGROUP: dolibarr-api-mcp.Documentation
|
||||
INGROUP: dolibarr-api-mcp
|
||||
REPO: https://git.mokoconsulting.tech/MokoConsulting/dolibarr-api-mcp
|
||||
PATH: /SECURITY.md
|
||||
VERSION: 09.39.00
|
||||
VERSION: 09.42.00
|
||||
BRIEF: Security vulnerability reporting and handling policy
|
||||
-->
|
||||
|
||||
|
||||
Submodule mcp/servers/mokogitea_api deleted from 44e1259c3e
@@ -14,7 +14,7 @@
|
||||
DEFGROUP:
|
||||
INGROUP: Project.Documentation
|
||||
REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoCli-Template-Generic
|
||||
VERSION: 09.39.00
|
||||
VERSION: 09.42.00
|
||||
PATH: ./CONTRIBUTING.md
|
||||
BRIEF: Contribution guidelines for the project
|
||||
-->
|
||||
|
||||
@@ -23,7 +23,7 @@ DEFGROUP: [PROJECT_NAME]
|
||||
INGROUP: [PROJECT_NAME].Documentation
|
||||
REPO: [REPOSITORY_URL]
|
||||
PATH: /SECURITY.md
|
||||
VERSION: 09.39.00
|
||||
VERSION: 09.42.00
|
||||
BRIEF: Security vulnerability reporting and handling policy
|
||||
-->
|
||||
|
||||
|
||||
Submodule mcp/servers/windows/mcp_windows deleted from 4ae12d459b
@@ -12,7 +12,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
<!-- Files to check -->
|
||||
<file>lib</file>
|
||||
<file>validate</file>
|
||||
<file>automation</file>
|
||||
<file>cli</file>
|
||||
|
||||
<!-- Exclude vendor and other dependencies -->
|
||||
|
||||
@@ -2363,3 +2363,711 @@ parameters:
|
||||
identifier: deadCode.unreachable
|
||||
count: 2
|
||||
path: validate/scan_drift.php
|
||||
-
|
||||
message: '#^Function apiRequest\(\) has parameter \$body with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/branch_protect_org.php
|
||||
-
|
||||
message: '#^Function apiRequest\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/branch_protect_org.php
|
||||
-
|
||||
message: '#^Method BranchRenameCli\:\:apiRequest\(\) has parameter \$body with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/branch_rename.php
|
||||
-
|
||||
message: '#^Method BranchRenameCli\:\:apiRequest\(\) has parameter \$headers with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/branch_rename.php
|
||||
-
|
||||
message: '#^Method BranchRenameCli\:\:apiRequest\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/branch_rename.php
|
||||
-
|
||||
message: '#^Method BulkWorkflowPushCli\:\:apiRequest\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/bulk_workflow_push.php
|
||||
-
|
||||
message: '#^Method BulkWorkflowPushCli\:\:fetchOrgRepos\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/bulk_workflow_push.php
|
||||
-
|
||||
message: '#^Method BulkWorkflowTriggerCli\:\:apiRequest\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/bulk_workflow_trigger.php
|
||||
-
|
||||
message: '#^Method BulkWorkflowTriggerCli\:\:buildRepoList\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/bulk_workflow_trigger.php
|
||||
-
|
||||
message: '#^Method ClientDashboardCli\:\:discoverClients\(\) never returns null so it can be removed from the return type\.$#'
|
||||
count: 1
|
||||
path: cli/client_dashboard.php
|
||||
-
|
||||
message: '#^Method ClientInventoryCli\:\:apiRequest\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/client_inventory.php
|
||||
-
|
||||
message: '#^Method ClientInventoryCli\:\:checkVariables\(\) has parameter \$requiredVars with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/client_inventory.php
|
||||
-
|
||||
message: '#^Method ClientInventoryCli\:\:fetchOrgRepos\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/client_inventory.php
|
||||
-
|
||||
message: '#^Method ClientInventoryCli\:\:fetchOrgs\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/client_inventory.php
|
||||
-
|
||||
message: '#^Method ClientProvisionCli\:\:giteaApi\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/client_provision.php
|
||||
-
|
||||
message: '#^Method ClientProvisionCli\:\:grafanaApi\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/client_provision.php
|
||||
-
|
||||
message: '#^Method ClientProvisionCli\:\:httpRequest\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/client_provision.php
|
||||
-
|
||||
message: '#^Method ClientProvisionCli\:\:printSummary\(\) overrides method MokoCli\\CliFramework\:\:printSummary\(\) but misses parameter \#1 \$passed\.$#'
|
||||
count: 1
|
||||
path: cli/client_provision.php
|
||||
-
|
||||
message: '#^Method ClientProvisionCli\:\:printSummary\(\) overrides method MokoCli\\CliFramework\:\:printSummary\(\) but misses parameter \#2 \$failed\.$#'
|
||||
count: 1
|
||||
path: cli/client_provision.php
|
||||
-
|
||||
message: '#^Method ClientProvisionCli\:\:printSummary\(\) overrides method MokoCli\\CliFramework\:\:printSummary\(\) but misses parameter \#3 \$elapsed\.$#'
|
||||
count: 1
|
||||
path: cli/client_provision.php
|
||||
-
|
||||
message: '#^Private method ClientProvisionCli\:\:printSummary\(\) overriding protected method MokoCli\\CliFramework\:\:printSummary\(\) should be protected or public\.$#'
|
||||
count: 1
|
||||
path: cli/client_provision.php
|
||||
-
|
||||
message: '#^Return type int of method ClientProvisionCli\:\:printSummary\(\) is not covariant with return type void of method MokoCli\\CliFramework\:\:printSummary\(\)\.$#'
|
||||
count: 1
|
||||
path: cli/client_provision.php
|
||||
-
|
||||
message: '#^Method CompletionCli\:\:generateBash\(\) has parameter \$commands with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/completion.php
|
||||
-
|
||||
message: '#^Method CompletionCli\:\:generateBash\(\) has parameter \$flags with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/completion.php
|
||||
-
|
||||
message: '#^Method CompletionCli\:\:generateZsh\(\) has parameter \$commands with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/completion.php
|
||||
-
|
||||
message: '#^Method CompletionCli\:\:generateZsh\(\) has parameter \$flags with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/completion.php
|
||||
-
|
||||
message: '#^Method CreateProjectCli\:\:createProject\(\) has parameter \$template with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/create_project.php
|
||||
-
|
||||
message: '#^Method CreateProjectCli\:\:graphql\(\) has parameter \$variables with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/create_project.php
|
||||
-
|
||||
message: '#^Method CreateProjectCli\:\:graphql\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/create_project.php
|
||||
-
|
||||
message: '#^Method CreateProjectCli\:\:parseTemplate\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 2
|
||||
path: cli/create_project.php
|
||||
-
|
||||
message: '#^Method CreateProjectCli\:\:restGet\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/create_project.php
|
||||
-
|
||||
message: '#^Method DeployJoomla\:\:buildDeployMap\(\) has parameter \$ext with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/deploy_joomla.php
|
||||
-
|
||||
message: '#^Method DeployJoomla\:\:dryRunWalk\(\) has parameter \$deployMap with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/deploy_joomla.php
|
||||
-
|
||||
message: '#^Method DeployJoomla\:\:firstExistingDir\(\) has parameter \$candidates with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/deploy_joomla.php
|
||||
-
|
||||
message: '#^Method DeployJoomla\:\:getManifestDestination\(\) has parameter \$ext with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/deploy_joomla.php
|
||||
-
|
||||
message: '#^Method DeployJoomla\:\:getManifestFilename\(\) has parameter \$ext with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/deploy_joomla.php
|
||||
-
|
||||
message: '#^Method DeployJoomla\:\:mapComponent\(\) has parameter \$ext with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/deploy_joomla.php
|
||||
-
|
||||
message: '#^Method DeployJoomla\:\:mapComponent\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/deploy_joomla.php
|
||||
-
|
||||
message: '#^Method DeployJoomla\:\:mapFile\(\) has parameter \$ext with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/deploy_joomla.php
|
||||
-
|
||||
message: '#^Method DeployJoomla\:\:mapFile\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/deploy_joomla.php
|
||||
-
|
||||
message: '#^Method DeployJoomla\:\:mapLanguage\(\) has parameter \$ext with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/deploy_joomla.php
|
||||
-
|
||||
message: '#^Method DeployJoomla\:\:mapLanguage\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/deploy_joomla.php
|
||||
-
|
||||
message: '#^Method DeployJoomla\:\:mapLibrary\(\) has parameter \$ext with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/deploy_joomla.php
|
||||
-
|
||||
message: '#^Method DeployJoomla\:\:mapLibrary\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/deploy_joomla.php
|
||||
-
|
||||
message: '#^Method DeployJoomla\:\:mapModule\(\) has parameter \$ext with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/deploy_joomla.php
|
||||
-
|
||||
message: '#^Method DeployJoomla\:\:mapModule\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/deploy_joomla.php
|
||||
-
|
||||
message: '#^Method DeployJoomla\:\:mapPackage\(\) has parameter \$ext with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/deploy_joomla.php
|
||||
-
|
||||
message: '#^Method DeployJoomla\:\:mapPackage\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/deploy_joomla.php
|
||||
-
|
||||
message: '#^Method DeployJoomla\:\:mapPlugin\(\) has parameter \$ext with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/deploy_joomla.php
|
||||
-
|
||||
message: '#^Method DeployJoomla\:\:mapPlugin\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/deploy_joomla.php
|
||||
-
|
||||
message: '#^Method DeployJoomla\:\:mapTemplate\(\) has parameter \$ext with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/deploy_joomla.php
|
||||
-
|
||||
message: '#^Method DeployJoomla\:\:mapTemplate\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/deploy_joomla.php
|
||||
-
|
||||
message: '#^Parameter \#2 \.\.\.\$args of method phpseclib3\\Net\\SSH2\:\:login\(\) expects array\<array\>\|phpseclib3\\Crypt\\Common\\PrivateKey\|phpseclib3\\System\\SSH\\Agent\|string\|null, phpseclib3\\Crypt\\Common\\AsymmetricKey given\.$#'
|
||||
count: 1
|
||||
path: cli/deploy_joomla.php
|
||||
-
|
||||
message: '#^Method GrafanaDashboardCli\:\:apiRequest\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/grafana_dashboard.php
|
||||
-
|
||||
message: '#^Method JoomlaBuildCli\:\:parseManifest\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/joomla_build.php
|
||||
-
|
||||
message: '#^Method JoomlaBuildCli\:\:typePrefix\(\) has parameter \$meta with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/joomla_build.php
|
||||
-
|
||||
message: '#^Method JoomlaMetadataValidateCli\:\:compare\(\) has parameter \$joomlaXml with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/joomla_metadata_validate.php
|
||||
-
|
||||
message: '#^Method JoomlaMetadataValidateCli\:\:compare\(\) has parameter \$metadata with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/joomla_metadata_validate.php
|
||||
-
|
||||
message: '#^Method JoomlaMetadataValidateCli\:\:compare\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/joomla_metadata_validate.php
|
||||
-
|
||||
message: '#^Method JoomlaMetadataValidateCli\:\:findJoomlaManifest\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/joomla_metadata_validate.php
|
||||
-
|
||||
message: '#^Method JoomlaMetadataValidateCli\:\:loadMetadata\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/joomla_metadata_validate.php
|
||||
-
|
||||
message: '#^Method JoomlaMetadataValidateCli\:\:printResults\(\) has parameter \$results with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/joomla_metadata_validate.php
|
||||
-
|
||||
message: '#^Call to an undefined method LicenseManage\:\:isDryRun\(\)\.$#'
|
||||
count: 7
|
||||
path: cli/license_manage.php
|
||||
-
|
||||
message: '#^Method LicenseManage\:\:apiDelete\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/license_manage.php
|
||||
-
|
||||
message: '#^Method LicenseManage\:\:apiGet\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/license_manage.php
|
||||
-
|
||||
message: '#^Method LicenseManage\:\:apiPatch\(\) has parameter \$data with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/license_manage.php
|
||||
-
|
||||
message: '#^Method LicenseManage\:\:apiPatch\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/license_manage.php
|
||||
-
|
||||
message: '#^Method LicenseManage\:\:apiPost\(\) has parameter \$data with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/license_manage.php
|
||||
-
|
||||
message: '#^Method LicenseManage\:\:apiPost\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/license_manage.php
|
||||
-
|
||||
message: '#^Method LicenseManage\:\:apiRequest\(\) has parameter \$data with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/license_manage.php
|
||||
-
|
||||
message: '#^Method LicenseManage\:\:apiRequest\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/license_manage.php
|
||||
-
|
||||
message: '#^Parameter \#1 \$passed of method MokoCli\\CliFramework\:\:status\(\) expects bool, string given\.$#'
|
||||
count: 4
|
||||
path: cli/license_manage.php
|
||||
-
|
||||
message: '#^Parameter \#2 \$label of method MokoCli\\CliFramework\:\:status\(\) expects string, false given\.$#'
|
||||
count: 1
|
||||
path: cli/license_manage.php
|
||||
-
|
||||
message: '#^Parameter \#2 \$label of method MokoCli\\CliFramework\:\:status\(\) expects string, true given\.$#'
|
||||
count: 2
|
||||
path: cli/license_manage.php
|
||||
-
|
||||
message: '#^Call to an undefined method ManifestDetectCli\:\:sectionHeader\(\)\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_detect.php
|
||||
-
|
||||
message: '#^Method ManifestDetectCli\:\:computeDiff\(\) has parameter \$current with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_detect.php
|
||||
-
|
||||
message: '#^Method ManifestDetectCli\:\:computeDiff\(\) has parameter \$detected with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_detect.php
|
||||
-
|
||||
message: '#^Method ManifestDetectCli\:\:computeDiff\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_detect.php
|
||||
-
|
||||
message: '#^Method ManifestDetectCli\:\:detectAll\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_detect.php
|
||||
-
|
||||
message: '#^Method ManifestDetectCli\:\:detectDolibarr\(\) has parameter \$fields with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_detect.php
|
||||
-
|
||||
message: '#^Method ManifestDetectCli\:\:detectGeneric\(\) has parameter \$fields with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_detect.php
|
||||
-
|
||||
message: '#^Method ManifestDetectCli\:\:detectGo\(\) has parameter \$fields with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_detect.php
|
||||
-
|
||||
message: '#^Method ManifestDetectCli\:\:detectJoomla\(\) has parameter \$fields with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_detect.php
|
||||
-
|
||||
message: '#^Method ManifestDetectCli\:\:detectNode\(\) has parameter \$fields with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_detect.php
|
||||
-
|
||||
message: '#^Method ManifestDetectCli\:\:fetchManifest\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_detect.php
|
||||
-
|
||||
message: '#^Method ManifestDetectCli\:\:pushManifest\(\) has parameter \$current with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_detect.php
|
||||
-
|
||||
message: '#^Method ManifestDetectCli\:\:pushManifest\(\) has parameter \$update with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_detect.php
|
||||
-
|
||||
message: '#^Method ManifestIntegrityCli\:\:applyFixes\(\) has parameter \$current with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_integrity.php
|
||||
-
|
||||
message: '#^Method ManifestIntegrityCli\:\:applyFixes\(\) has parameter \$issues with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_integrity.php
|
||||
-
|
||||
message: '#^Method ManifestIntegrityCli\:\:fetchManifest\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_integrity.php
|
||||
-
|
||||
message: '#^Method ManifestIntegrityCli\:\:fetchOrgRepos\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_integrity.php
|
||||
-
|
||||
message: '#^Method ManifestIntegrityCli\:\:printIssues\(\) has parameter \$issues with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_integrity.php
|
||||
-
|
||||
message: '#^Method ManifestIntegrityCli\:\:runDetect\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_integrity.php
|
||||
-
|
||||
message: '#^Method ManifestIntegrityCli\:\:validate\(\) has parameter \$current with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_integrity.php
|
||||
-
|
||||
message: '#^Method ManifestIntegrityCli\:\:validate\(\) has parameter \$detected with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_integrity.php
|
||||
-
|
||||
message: '#^Method ManifestIntegrityCli\:\:validate\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_integrity.php
|
||||
-
|
||||
message: '#^Method ManifestIntegrityCli\:\:validateManifestOnly\(\) has parameter \$manifest with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_integrity.php
|
||||
-
|
||||
message: '#^Method ManifestIntegrityCli\:\:validateManifestOnly\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_integrity.php
|
||||
-
|
||||
message: '#^Method ManifestIntegrityCli\:\:validatePlatformStructure\(\) has parameter \$manifest with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_integrity.php
|
||||
-
|
||||
message: '#^Method ManifestIntegrityCli\:\:validatePlatformStructure\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_integrity.php
|
||||
-
|
||||
message: '#^Constant ManifestReadCli\:\:JOOMLA_XML_ROOTS is unused\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_read.php
|
||||
-
|
||||
message: '#^Method ManifestReadCli\:\:addAliases\(\) has parameter \$fields with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_read.php
|
||||
-
|
||||
message: '#^Method ManifestReadCli\:\:addAliases\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_read.php
|
||||
-
|
||||
message: '#^Method ManifestReadCli\:\:autoDetect\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_read.php
|
||||
-
|
||||
message: '#^Method ManifestReadCli\:\:detectDolibarr\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_read.php
|
||||
-
|
||||
message: '#^Method ManifestReadCli\:\:detectJoomla\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_read.php
|
||||
-
|
||||
message: '#^Method ManifestReadCli\:\:fetchFromApi\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_read.php
|
||||
-
|
||||
message: '#^Method ManifestReadCli\:\:outputFields\(\) has parameter \$fields with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/manifest_read.php
|
||||
-
|
||||
message: '#^Method PackageBuildCli\:\:addDirectoryToZip\(\) has parameter \$excludes with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/package_build.php
|
||||
-
|
||||
message: '#^Method PlatformDetectCli\:\:apiRequest\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/platform_detect.php
|
||||
-
|
||||
message: '#^Method ReleaseCascadeCli\:\:cascadeToChannel\(\) has parameter \$downloads with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/release_cascade.php
|
||||
-
|
||||
message: '#^Method ReleaseCascadeCli\:\:getLowerChannels\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/release_cascade.php
|
||||
-
|
||||
message: '#^Method ReleaseCascadeCli\:\:giteaApi\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/release_cascade.php
|
||||
-
|
||||
message: '#^Method ReleaseCreateCli\:\:giteaApi\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/release_create.php
|
||||
-
|
||||
message: '#^Method ReleaseManageCli\:\:getReleaseByTag\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/release_manage.php
|
||||
-
|
||||
message: '#^Method ReleaseManageCli\:\:releaseGiteaApi\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/release_manage.php
|
||||
-
|
||||
message: '#^Method ReleaseMirrorCli\:\:giteaApi\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/release_mirror.php
|
||||
-
|
||||
message: '#^Method ReleaseMirrorCli\:\:githubApi\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/release_mirror.php
|
||||
-
|
||||
message: '#^Strict comparison using \=\=\= between mixed~\(0\|0\.0\|''''\|''0''\|array\{\}\|false\|null\) and '''' will always evaluate to false\.$#'
|
||||
count: 1
|
||||
path: cli/release_notes.php
|
||||
-
|
||||
message: '#^Method ReleasePackageCli\:\:addDirToZip\(\) has parameter \$excludes with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/release_package.php
|
||||
-
|
||||
message: '#^Method ReleasePackageCli\:\:isExcluded\(\) has parameter \$patterns with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/release_package.php
|
||||
-
|
||||
message: '#^Method ReleasePromoteCli\:\:giteaApi\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/release_promote.php
|
||||
-
|
||||
message: '#^Variable \$token in empty\(\) always exists and is not falsy\.$#'
|
||||
count: 1
|
||||
path: cli/release_publish.php
|
||||
-
|
||||
message: '#^Property ReleaseValidateCli\:\:\$results type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/release_validate.php
|
||||
-
|
||||
message: '#^Property ReleaseVerifyCli\:\:\$results type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/release_verify.php
|
||||
-
|
||||
message: '#^Call to an undefined method MokoCli\\GitPlatformAdapter\:\:createRepository\(\)\.$#'
|
||||
count: 1
|
||||
path: cli/repo_wizard.php
|
||||
-
|
||||
message: '#^Method RepoWizard\:\:choose\(\) has parameter \$options with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/repo_wizard.php
|
||||
-
|
||||
message: '#^Method RepoWizard\:\:generateFiles\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/repo_wizard.php
|
||||
-
|
||||
message: '#^Offset 0 on non\-empty\-list\<string\> on left side of \?\? always exists and is not nullable\.$#'
|
||||
count: 1
|
||||
path: cli/repo_wizard.php
|
||||
-
|
||||
message: '#^Property RepoWizard\:\:\$answers type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/repo_wizard.php
|
||||
-
|
||||
message: '#^Method ScaffoldClientCli\:\:apiRequest\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/scaffold_client.php
|
||||
-
|
||||
message: '#^Method ThemeLintCli\:\:findFiles\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/theme_lint.php
|
||||
-
|
||||
message: '#^Offset 1 on array\{list\<string\>, list\<non\-falsy\-string\>\} on left side of \?\? always exists and is not nullable\.$#'
|
||||
count: 1
|
||||
path: cli/theme_vars_check.php
|
||||
-
|
||||
message: '#^Method UpdatesXmlSyncCli\:\:apiCall\(\) has parameter \$data with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/updates_xml_sync.php
|
||||
-
|
||||
message: '#^Method UpdatesXmlSyncCli\:\:apiCall\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/updates_xml_sync.php
|
||||
-
|
||||
message: '#^Offset ''alpha''\|''beta''\|''dev''\|''rc'' on array\{dev\: ''\-dev'', alpha\: ''\-alpha'', beta\: ''\-beta'', rc\: ''\-rc''\} on left side of \?\? always exists and is not nullable\.$#'
|
||||
count: 1
|
||||
path: cli/version_auto_bump.php
|
||||
-
|
||||
message: '#^Ternary operator condition is always true\.$#'
|
||||
count: 1
|
||||
path: cli/version_auto_bump.php
|
||||
-
|
||||
message: '#^Variable \$updatedFiles on left side of \?\? always exists and is not nullable\.$#'
|
||||
count: 1
|
||||
path: cli/version_bump.php
|
||||
-
|
||||
message: '#^Method VersionBumpRemoteCli\:\:giteaApi\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/version_bump_remote.php
|
||||
-
|
||||
message: '#^Method VersionResetDevCli\:\:giteaApiCall\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/version_reset_dev.php
|
||||
-
|
||||
message: '#^Method WikiSyncCli\:\:apiGet\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/wiki_sync.php
|
||||
-
|
||||
message: '#^Method WikiSyncCli\:\:apiPatch\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/wiki_sync.php
|
||||
-
|
||||
message: '#^Method WikiSyncCli\:\:apiPost\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/wiki_sync.php
|
||||
-
|
||||
message: '#^Method WikiSyncCli\:\:apiWrite\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/wiki_sync.php
|
||||
-
|
||||
message: '#^Method WikiSyncCli\:\:discoverTemplateRepos\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/wiki_sync.php
|
||||
-
|
||||
message: '#^Method WikiSyncCli\:\:getStandardsPages\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/wiki_sync.php
|
||||
-
|
||||
message: '#^Property WikiSyncCli\:\:\$pages type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/wiki_sync.php
|
||||
-
|
||||
message: '#^Property WikiSyncCli\:\:\$targetRepos type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/wiki_sync.php
|
||||
-
|
||||
message: '#^Method WorkflowSyncCli\:\:apiRequest\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/workflow_sync.php
|
||||
-
|
||||
message: '#^Method WorkflowSyncCli\:\:deleteOrphanWorkflows\(\) has parameter \$templateNames with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/workflow_sync.php
|
||||
-
|
||||
message: '#^Method WorkflowSyncCli\:\:fetchOrgRepos\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/workflow_sync.php
|
||||
-
|
||||
message: '#^Method WorkflowSyncCli\:\:listWorkflows\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: cli/workflow_sync.php
|
||||
-
|
||||
message: '#^Strict comparison using \=\=\= between string and false will always evaluate to false\.$#'
|
||||
count: 1
|
||||
path: cli/workflow_sync.php
|
||||
-
|
||||
message: '#^Constructor of class MokoCli\\CLIApp has an unused parameter \$description\.$#'
|
||||
count: 1
|
||||
path: lib/Enterprise/CliFramework.php
|
||||
-
|
||||
message: '#^Method MokoCli\\ManifestParser\:\:generate\(\) has parameter \$params with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: lib/Enterprise/ManifestParser.php
|
||||
-
|
||||
message: '#^Method MokoCli\\ManifestParser\:\:parse\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 4
|
||||
path: lib/Enterprise/ManifestParser.php
|
||||
-
|
||||
message: '#^Method MokoCli\\ManifestParser\:\:parseBuild\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: lib/Enterprise/ManifestParser.php
|
||||
-
|
||||
message: '#^Method MokoCli\\ManifestParser\:\:parseDeploy\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: lib/Enterprise/ManifestParser.php
|
||||
-
|
||||
message: '#^Method MokoCli\\ManifestParser\:\:parseGovernance\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: lib/Enterprise/ManifestParser.php
|
||||
-
|
||||
message: '#^Method MokoCli\\ManifestParser\:\:parseIdentity\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: lib/Enterprise/ManifestParser.php
|
||||
-
|
||||
message: '#^Method MokoCli\\ManifestParser\:\:parseLegacy\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: lib/Enterprise/ManifestParser.php
|
||||
-
|
||||
message: '#^Method MokoCli\\ManifestParser\:\:parseOverrides\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: lib/Enterprise/ManifestParser.php
|
||||
-
|
||||
message: '#^Method MokoCli\\ManifestParser\:\:parseScripts\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: lib/Enterprise/ManifestParser.php
|
||||
-
|
||||
message: '#^Method MokoCli\\ManifestParser\:\:tryParse\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: lib/Enterprise/ManifestParser.php
|
||||
-
|
||||
message: '#^Method MokoCli\\Plugins\\DolibarrPlugin\:\:getCommands\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: lib/Enterprise/Plugins/DolibarrPlugin.php
|
||||
-
|
||||
message: '#^Method MokoCli\\Plugins\\JoomlaPlugin\:\:getCommands\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: lib/Enterprise/Plugins/JoomlaPlugin.php
|
||||
-
|
||||
message: '#^Variable \$content on left side of \?\? always exists and is not nullable\.$#'
|
||||
count: 2
|
||||
path: lib/Enterprise/Plugins/McpServerPlugin.php
|
||||
-
|
||||
message: '#^Method MokoCli\\Plugins\\NodeJsPlugin\:\:getCommands\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: lib/Enterprise/Plugins/NodeJsPlugin.php
|
||||
-
|
||||
message: '#^Method MokoCli\\Plugins\\PythonPlugin\:\:getCommands\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: lib/Enterprise/Plugins/PythonPlugin.php
|
||||
-
|
||||
message: '#^Method MokoCli\\Plugins\\WordPressPlugin\:\:getCommands\(\) return type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: lib/Enterprise/Plugins/WordPressPlugin.php
|
||||
-
|
||||
message: '#^Call to static method platformPackageType\(\) on an unknown class MokoCli\\mokocliParser\.$#'
|
||||
count: 1
|
||||
path: lib/Enterprise/RepositorySynchronizer.php
|
||||
-
|
||||
message: '#^Method MokoCli\\RepositorySynchronizer\:\:generateManifestXml\(\) has parameter \$repoInfo with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: lib/Enterprise/RepositorySynchronizer.php
|
||||
-
|
||||
message: '#^Method MokoCli\\RepositorySynchronizer\:\:migrateManifest\(\) has parameter \$repoInfo with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: lib/Enterprise/RepositorySynchronizer.php
|
||||
-
|
||||
message: '#^Method MokoCli\\RepositorySynchronizer\:\:migrateManifest\(\) has parameter \$summary with no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: lib/Enterprise/RepositorySynchronizer.php
|
||||
-
|
||||
message: '#^Offset 1 on array\{non\-empty\-list\<array\{string, int\<\-1, max\>\}\>, non\-empty\-list\<array\{non\-empty\-string, int\<\-1, max\>\}\>\} in empty\(\) always exists and is not falsy\.$#'
|
||||
count: 1
|
||||
path: lib/Enterprise/SecurityValidator.php
|
||||
-
|
||||
message: '#^Property MokoCli\\SourceResolver\:\:\$apiCache type has no value type specified in iterable type array\.$#'
|
||||
count: 1
|
||||
path: lib/Enterprise/SourceResolver.php
|
||||
-
|
||||
message: '#^Undefined variable\: \$defTotal$#'
|
||||
count: 3
|
||||
path: validate/check_version_consistency.php
|
||||
|
||||
@@ -10,7 +10,6 @@ parameters:
|
||||
paths:
|
||||
- lib
|
||||
- validate
|
||||
- automation
|
||||
- cli
|
||||
excludePaths:
|
||||
analyseAndScan:
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
{
|
||||
"name": "exampleclient",
|
||||
"org": "ExampleClient",
|
||||
"gitea_url": "https://git.mokoconsulting.tech",
|
||||
|
||||
"variables": {
|
||||
"DEV_SYNC_HOST": "dev.exampleclient.com",
|
||||
"DEV_SYNC_PORT": "22",
|
||||
"DEV_SYNC_USER": "exampleclient",
|
||||
"DEV_SYNC_PATH": "/home/exampleclient/dev.exampleclient.com",
|
||||
"DEV_SITE_URL": "https://dev.exampleclient.com",
|
||||
"LIVE_SSH_HOST": "iad1-shared-b7-01.dreamhost.com",
|
||||
"LIVE_SSH_PORT": "22",
|
||||
"LIVE_SSH_USER": "exampleclient",
|
||||
"LIVE_SYNC_PATH": "/home/exampleclient/exampleclient.com",
|
||||
"RS_FTP_PATH_SUFFIX": "exampleclient.com"
|
||||
},
|
||||
|
||||
"secrets": {
|
||||
"DEV_SYNC_KEY": "@keys/exampleclient-dev.pem",
|
||||
"LIVE_SSH_KEY": "@keys/exampleclient-live.pem"
|
||||
},
|
||||
|
||||
"monitoring": {
|
||||
"urls": [
|
||||
"https://exampleclient.com",
|
||||
"https://dev.exampleclient.com"
|
||||
],
|
||||
"domains": [
|
||||
"exampleclient.com"
|
||||
],
|
||||
"grafana_dashboard": "monitoring/grafana/client-joomla-dashboard.json",
|
||||
"grafana_folder": "Clients"
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
# Enterprise Issue Management Configuration Template
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# Deploy to: .github/issue-management-config.yml
|
||||
|
||||
version: "1.0.0"
|
||||
|
||||
enterprise:
|
||||
organization:
|
||||
name: "ORGANIZATION_NAME"
|
||||
default_assignees:
|
||||
- "copilot"
|
||||
|
||||
projects:
|
||||
enabled: true
|
||||
default_project_number: null
|
||||
auto_add_issues: true
|
||||
|
||||
milestones:
|
||||
enabled: true
|
||||
auto_assign: true
|
||||
create_if_missing: true
|
||||
|
||||
labels:
|
||||
priority:
|
||||
critical:
|
||||
name: "priority/critical"
|
||||
color: "d73a4a"
|
||||
sla_hours: 4
|
||||
high:
|
||||
name: "priority/high"
|
||||
color: "ff9800"
|
||||
sla_hours: 24
|
||||
medium:
|
||||
name: "priority/medium"
|
||||
color: "fbca04"
|
||||
sla_hours: 72
|
||||
|
||||
automation:
|
||||
create_on_branch: true
|
||||
branch_patterns:
|
||||
- "dev/**"
|
||||
- "rc/**"
|
||||
close_on_merge: true
|
||||
close_on_branch_delete: true
|
||||
link_prs_to_issues: true
|
||||
create_sub_tasks_for_prs: true
|
||||
|
||||
sla:
|
||||
enabled: true
|
||||
timezone: "UTC"
|
||||
|
||||
audit:
|
||||
enabled: true
|
||||
retention_days: 365
|
||||
|
||||
metrics:
|
||||
enabled: true
|
||||
|
||||
error_handling:
|
||||
retry_on_failure: true
|
||||
max_retries: 3
|
||||
@@ -1,28 +0,0 @@
|
||||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es2021": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended"
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"rules": {
|
||||
"indent": ["error", 2],
|
||||
"linebreak-style": ["error", "unix"],
|
||||
"quotes": ["error", "single"],
|
||||
"semi": ["error", "always"],
|
||||
"no-unused-vars": ["warn"],
|
||||
"no-console": ["warn", { "allow": ["warn", "error"] }],
|
||||
"eqeqeq": ["error", "always"],
|
||||
"curly": ["error", "all"],
|
||||
"brace-style": ["error", "1tbs"],
|
||||
"no-trailing-spaces": "error",
|
||||
"no-multiple-empty-lines": ["error", { "max": 1 }],
|
||||
"eol-last": ["error", "always"]
|
||||
}
|
||||
}
|
||||
@@ -1,220 +0,0 @@
|
||||
# ============================================================
|
||||
# Local task tracking (not version controlled)
|
||||
# ============================================================
|
||||
TODO.md
|
||||
|
||||
# ============================================================
|
||||
# Environment and secrets
|
||||
# ============================================================
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
*.local.php
|
||||
*.secret.php
|
||||
configuration.php
|
||||
configuration.*.php
|
||||
configuration.local.php
|
||||
conf/conf.php
|
||||
conf/conf*.php
|
||||
secrets/
|
||||
*.secrets.*
|
||||
|
||||
# ============================================================
|
||||
# Logs, dumps and databases
|
||||
# ============================================================
|
||||
*.db
|
||||
*.db-journal
|
||||
*.dump
|
||||
*.log
|
||||
*.pid
|
||||
*.seed
|
||||
|
||||
|
||||
# ============================================================
|
||||
# OS / Editor / IDE cruft
|
||||
# ============================================================
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
desktop.ini
|
||||
Thumbs.db:encryptable
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
$RECYCLE.BIN/
|
||||
System Volume Information/
|
||||
*.lnk
|
||||
Icon?
|
||||
.idea/
|
||||
.settings/
|
||||
.claude/
|
||||
.claude-worktree*/
|
||||
.vscode/*
|
||||
!.vscode/tasks.json
|
||||
!.vscode/settings.json.example
|
||||
!.vscode/extensions.json
|
||||
*.code-workspace
|
||||
*.sublime*
|
||||
.project
|
||||
.buildpath
|
||||
.classpath
|
||||
*.bak
|
||||
*.swp
|
||||
*.swo
|
||||
*.tmp
|
||||
*.old
|
||||
*.orig
|
||||
|
||||
# ============================================================
|
||||
# Dev scripts and scratch
|
||||
# ============================================================
|
||||
TODO.md
|
||||
todo*
|
||||
*ffs*
|
||||
|
||||
# ============================================================
|
||||
# SFTP / sync tools
|
||||
# ============================================================
|
||||
sftp-config*.json
|
||||
sftp-config.json.template
|
||||
sftp-settings.json
|
||||
|
||||
# ============================================================
|
||||
# Sublime SFTP / FTP sync
|
||||
# ============================================================
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
*.sublime-settings
|
||||
.libsass.json
|
||||
*.ffs*
|
||||
|
||||
# ============================================================
|
||||
# Replit / cloud IDE
|
||||
# ============================================================
|
||||
.replit
|
||||
replit.md
|
||||
|
||||
# ============================================================
|
||||
# Archives / release artifacts
|
||||
# ============================================================
|
||||
*.7z
|
||||
*.rar
|
||||
*.tar
|
||||
*.tar.gz
|
||||
*.tgz
|
||||
*.zip
|
||||
artifacts/
|
||||
release/
|
||||
releases/
|
||||
|
||||
# ============================================================
|
||||
# Build outputs and site generators
|
||||
# ============================================================
|
||||
.mkdocs-build/
|
||||
.cache/
|
||||
.parcel-cache/
|
||||
build/
|
||||
dist/
|
||||
out/
|
||||
/site/
|
||||
*.map
|
||||
*.css.map
|
||||
*.js.map
|
||||
*.tsbuildinfo
|
||||
|
||||
# ============================================================
|
||||
# CI / test artifacts
|
||||
# ============================================================
|
||||
.coverage
|
||||
.coverage.*
|
||||
coverage/
|
||||
coverage.xml
|
||||
htmlcov/
|
||||
junit.xml
|
||||
reports/
|
||||
test-results/
|
||||
tests/_output/
|
||||
.github/local/
|
||||
.github/workflows/*.log
|
||||
|
||||
# ============================================================
|
||||
# Node / JavaScript
|
||||
# ============================================================
|
||||
node_modules/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
.pnpm-store/
|
||||
.yarn/
|
||||
.npmrc
|
||||
.eslintcache
|
||||
package-lock.json
|
||||
|
||||
# ============================================================
|
||||
# PHP / Composer tooling
|
||||
# ============================================================
|
||||
/vendor/
|
||||
!src/media/vendor/
|
||||
composer.lock
|
||||
*.phar
|
||||
codeception.phar
|
||||
.phpunit.result.cache
|
||||
.php_cs.cache
|
||||
.php-cs-fixer.cache
|
||||
.phpstan.cache
|
||||
.phplint-cache
|
||||
phpmd-cache/
|
||||
.psalm/
|
||||
.rector/
|
||||
|
||||
# ============================================================
|
||||
# Python
|
||||
# ============================================================
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*.pyc
|
||||
*$py.class
|
||||
*.so
|
||||
.Python
|
||||
.eggs/
|
||||
*.egg
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
MANIFEST
|
||||
develop-eggs/
|
||||
downloads/
|
||||
eggs/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
ENV/
|
||||
env/
|
||||
.venv/
|
||||
venv/
|
||||
.pytest_cache/
|
||||
.mypy_cache/
|
||||
.ruff_cache/
|
||||
.pyright/
|
||||
.tox/
|
||||
.nox/
|
||||
*.cover
|
||||
*.coverage
|
||||
hypothesis/
|
||||
|
||||
# ============================================================
|
||||
# Local wiki clone (not version controlled)
|
||||
# ============================================================
|
||||
wiki/
|
||||
|
||||
# ============================================================
|
||||
# Joomla runtime / development
|
||||
# ============================================================
|
||||
cache/
|
||||
tmp/
|
||||
logs/
|
||||
configuration.php
|
||||
user.css
|
||||
user.js
|
||||
colors_custom.css
|
||||
modulebuilder.txt
|
||||
administrator/components/com_akeebabackup/backup/
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"extends": "htmlhint:recommended",
|
||||
"tagname-lowercase": true,
|
||||
"attr-lowercase": true,
|
||||
"attr-value-double-quotes": true,
|
||||
"doctype-first": true,
|
||||
"tag-pair": true,
|
||||
"spec-char-escape": true,
|
||||
"id-unique": true,
|
||||
"src-not-empty": true,
|
||||
"attr-no-duplication": true,
|
||||
"title-require": true,
|
||||
"alt-require": true,
|
||||
"doctype-html5": true,
|
||||
"style-disabled": false,
|
||||
"inline-style-disabled": false,
|
||||
"inline-script-disabled": false,
|
||||
"space-tab-mixed-disabled": "space",
|
||||
"id-class-ad-disabled": false,
|
||||
"href-abs-or-rel": false,
|
||||
"attr-unsafe-chars": true
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"semi": true,
|
||||
"trailingComma": "es5",
|
||||
"singleQuote": true,
|
||||
"printWidth": 100,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"endOfLine": "lf",
|
||||
"arrowParens": "always",
|
||||
"bracketSpacing": true
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
#
|
||||
# This file is part of a Moko Consulting project.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Pylint configuration for MokoCli projects
|
||||
|
||||
[MASTER]
|
||||
# Python code to execute, usually for sys.path manipulation
|
||||
init-hook='import sys; sys.path.append(".")'
|
||||
|
||||
# Use multiple processes to speed up Pylint
|
||||
jobs=0
|
||||
|
||||
# Pickle collected data for later comparisons
|
||||
persistent=yes
|
||||
|
||||
# List of plugins (as comma separated values of python module names)
|
||||
load-plugins=
|
||||
|
||||
# Minimum Python version to use for version dependent checks
|
||||
py-version=3.8
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
# Disable specific messages
|
||||
disable=
|
||||
missing-module-docstring,
|
||||
missing-function-docstring,
|
||||
too-few-public-methods,
|
||||
too-many-arguments,
|
||||
too-many-locals,
|
||||
too-many-branches,
|
||||
too-many-statements,
|
||||
duplicate-code,
|
||||
fixme
|
||||
|
||||
[REPORTS]
|
||||
# Set the output format
|
||||
output-format=text
|
||||
|
||||
# Tells whether to display a full report or only the messages
|
||||
reports=no
|
||||
|
||||
# Activate the evaluation score
|
||||
score=yes
|
||||
|
||||
[BASIC]
|
||||
# Good variable names
|
||||
good-names=i,j,k,ex,Run,_,id,pk
|
||||
|
||||
# Regular expressions for acceptable names
|
||||
variable-rgx=[a-z_][a-z0-9_]{0,30}$
|
||||
const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
|
||||
class-rgx=[A-Z_][a-zA-Z0-9]+$
|
||||
function-rgx=[a-z_][a-z0-9_]{1,50}$
|
||||
method-rgx=[a-z_][a-z0-9_]{1,50}$
|
||||
|
||||
[FORMAT]
|
||||
# Maximum number of characters on a single line
|
||||
max-line-length=100
|
||||
|
||||
# Maximum number of lines in a module
|
||||
max-module-lines=1000
|
||||
|
||||
# String used for indentation
|
||||
indent-string=' '
|
||||
|
||||
[DESIGN]
|
||||
# Maximum number of arguments for function / method
|
||||
max-args=7
|
||||
|
||||
# Maximum number of attributes for a class
|
||||
max-attributes=10
|
||||
|
||||
[IMPORTS]
|
||||
# Deprecated modules which should not be used
|
||||
deprecated-modules=optparse,imp
|
||||
|
||||
[CLASSES]
|
||||
# List of method names used to declare instance attributes
|
||||
defining-attr-methods=__init__,__new__,setUp
|
||||
|
||||
# List of valid names for the first argument in a class method
|
||||
valid-classmethod-first-arg=cls
|
||||
|
||||
# List of valid names for the first argument in a metaclass class method
|
||||
valid-metaclass-classmethod-first-arg=mcs
|
||||
|
||||
[EXCEPTIONS]
|
||||
# Exceptions that will emit a warning when caught
|
||||
overgeneral-exceptions=builtins.Exception
|
||||
@@ -1,306 +0,0 @@
|
||||
<!--
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# FILE INFORMATION
|
||||
DEFGROUP: MokoPlatform.Templates
|
||||
INGROUP: MokoPlatform
|
||||
REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
PATH: /templates/configs/README.md
|
||||
BRIEF: Code quality and security tool configuration templates
|
||||
-->
|
||||
|
||||
# Code Quality Configuration Templates
|
||||
|
||||
This directory contains standardized configuration files for code quality, linting, and security tools used across mokocli projects.
|
||||
|
||||
## Available Configurations
|
||||
|
||||
### PHP Tools
|
||||
|
||||
#### `phpcs.xml` - PHP_CodeSniffer
|
||||
**Purpose**: Enforce PHP coding standards (PSR-12 based)
|
||||
|
||||
**Usage**:
|
||||
```bash
|
||||
# Copy to your project root
|
||||
cp phpcs.xml /path/to/your/project/
|
||||
|
||||
# Run PHPCS
|
||||
phpcs --standard=phpcs.xml src/
|
||||
|
||||
# Auto-fix issues
|
||||
phpcbf --standard=phpcs.xml src/
|
||||
```
|
||||
|
||||
**Features**:
|
||||
- PSR-12 compliance
|
||||
- Line length limits (120 chars)
|
||||
- Forbidden functions detection (eval, var_dump, etc.)
|
||||
- Commented-out code detection
|
||||
|
||||
#### `phpstan.neon` - PHPStan
|
||||
**Purpose**: Static analysis for PHP code
|
||||
|
||||
**Usage**:
|
||||
```bash
|
||||
# Copy to your project root
|
||||
cp phpstan.neon /path/to/your/project/
|
||||
|
||||
# Install PHPStan
|
||||
composer require --dev phpstan/phpstan
|
||||
|
||||
# Run analysis
|
||||
phpstan analyse
|
||||
```
|
||||
|
||||
**Configuration**:
|
||||
- Level 5 analysis (adjust as needed)
|
||||
- Checks for type errors, dead code, and more
|
||||
- Configurable ignore patterns
|
||||
|
||||
#### `psalm.xml` - Psalm
|
||||
**Purpose**: Advanced static analysis for PHP
|
||||
|
||||
**Usage**:
|
||||
```bash
|
||||
# Copy to your project root
|
||||
cp psalm.xml /path/to/your/project/
|
||||
|
||||
# Install Psalm
|
||||
composer require --dev vimeo/psalm
|
||||
|
||||
# Initialize and run
|
||||
psalm --init
|
||||
psalm
|
||||
```
|
||||
|
||||
**Configuration**:
|
||||
- Error level 4 (balanced strictness)
|
||||
- Finds unused code (optional)
|
||||
- Customizable issue handlers
|
||||
|
||||
### JavaScript/TypeScript Tools
|
||||
|
||||
#### `.eslintrc.json` - ESLint
|
||||
**Purpose**: Identify and fix JavaScript code issues
|
||||
|
||||
**Usage**:
|
||||
```bash
|
||||
# Copy to your project root
|
||||
cp .eslintrc.json /path/to/your/project/
|
||||
|
||||
# Install ESLint
|
||||
npm install --save-dev eslint
|
||||
|
||||
# Run linting
|
||||
npx eslint .
|
||||
|
||||
# Auto-fix issues
|
||||
npx eslint . --fix
|
||||
```
|
||||
|
||||
**Features**:
|
||||
- ES2021 support
|
||||
- Tab indentation (2-space visual width)
|
||||
- Unix line endings
|
||||
- Single quotes for strings
|
||||
- Semicolon enforcement
|
||||
|
||||
#### `.prettierrc.json` - Prettier
|
||||
**Purpose**: Opinionated code formatter for JavaScript/TypeScript
|
||||
|
||||
**Usage**:
|
||||
```bash
|
||||
# Copy to your project root
|
||||
cp .prettierrc.json /path/to/your/project/
|
||||
|
||||
# Install Prettier
|
||||
npm install --save-dev prettier
|
||||
|
||||
# Check formatting
|
||||
npx prettier --check .
|
||||
|
||||
# Auto-format
|
||||
npx prettier --write .
|
||||
```
|
||||
|
||||
**Configuration**:
|
||||
- 100 character line width
|
||||
- Single quotes
|
||||
- Trailing commas (ES5)
|
||||
- Tab indentation (2-space visual width)
|
||||
|
||||
### Python Tools
|
||||
|
||||
#### `.pylintrc` - Pylint
|
||||
**Purpose**: Python code analysis and style checking
|
||||
|
||||
**Usage**:
|
||||
```bash
|
||||
# Copy to your project root
|
||||
cp .pylintrc /path/to/your/project/
|
||||
|
||||
# Install Pylint
|
||||
pip install pylint
|
||||
|
||||
# Run analysis
|
||||
pylint **/*.py
|
||||
```
|
||||
|
||||
**Features**:
|
||||
- PEP 8 compliance
|
||||
- 100 character line limit
|
||||
- Configurable message disabling
|
||||
- Custom naming conventions
|
||||
|
||||
#### `pyproject.toml` - Python Project Configuration
|
||||
**Purpose**: Unified configuration for Black, isort, mypy, and pytest
|
||||
|
||||
**Usage**:
|
||||
```bash
|
||||
# Copy to your project root
|
||||
cp pyproject.toml /path/to/your/project/
|
||||
|
||||
# Install tools
|
||||
pip install black isort mypy pytest pytest-cov
|
||||
|
||||
# Run Black formatter
|
||||
black .
|
||||
|
||||
# Sort imports with isort
|
||||
isort .
|
||||
|
||||
# Type check with mypy
|
||||
mypy src/
|
||||
|
||||
# Run tests with coverage
|
||||
pytest --cov=src
|
||||
```
|
||||
|
||||
**Tools Configured**:
|
||||
- **Black**: Opinionated Python formatter
|
||||
- **isort**: Import statement sorter
|
||||
- **mypy**: Static type checker
|
||||
- **pytest**: Test framework
|
||||
- **coverage**: Code coverage measurement
|
||||
|
||||
### HTML Tools
|
||||
|
||||
#### `.htmlhintrc` - HTMLHint
|
||||
**Purpose**: HTML5 validation and best practices
|
||||
|
||||
**Usage**:
|
||||
```bash
|
||||
# Copy to your project root
|
||||
cp .htmlhintrc /path/to/your/project/
|
||||
|
||||
# Install HTMLHint
|
||||
npm install -g htmlhint
|
||||
|
||||
# Run validation
|
||||
htmlhint **/*.html
|
||||
```
|
||||
|
||||
**Features**:
|
||||
- HTML5 doctype validation
|
||||
- Tag and attribute validation
|
||||
- Accessibility checks (alt, title requirements)
|
||||
- Style and script validation
|
||||
|
||||
## Integration with GitHub Actions
|
||||
|
||||
All these tools are integrated into the `code-quality.yml` workflow template. To use:
|
||||
|
||||
1. **Copy the workflow**:
|
||||
```bash
|
||||
cp templates/workflows/code-quality.yml.template .github/workflows/code-quality.yml
|
||||
```
|
||||
|
||||
2. **Copy relevant config files**:
|
||||
```bash
|
||||
# For PHP projects
|
||||
cp templates/configs/phpcs.xml .
|
||||
cp templates/configs/phpstan.neon .
|
||||
|
||||
# For JavaScript projects
|
||||
cp templates/configs/.eslintrc.json .
|
||||
cp templates/configs/.prettierrc.json .
|
||||
|
||||
# For Python projects
|
||||
cp templates/configs/.pylintrc .
|
||||
cp templates/configs/pyproject.toml .
|
||||
|
||||
# For HTML projects
|
||||
cp templates/configs/.htmlhintrc .
|
||||
```
|
||||
|
||||
3. **Customize for your project**: Adjust tool configurations based on your specific requirements
|
||||
|
||||
## Tool Installation
|
||||
|
||||
### PHP
|
||||
```bash
|
||||
# Via Composer
|
||||
composer require --dev squizlabs/php_codesniffer phpstan/phpstan vimeo/psalm
|
||||
```
|
||||
|
||||
### JavaScript/TypeScript
|
||||
```bash
|
||||
# Via npm
|
||||
npm install --save-dev eslint prettier @typescript-eslint/parser @typescript-eslint/eslint-plugin
|
||||
```
|
||||
|
||||
### Python
|
||||
```bash
|
||||
# Via pip
|
||||
pip install pylint black mypy isort pytest pytest-cov
|
||||
```
|
||||
|
||||
### HTML
|
||||
```bash
|
||||
# Via npm (global)
|
||||
npm install -g htmlhint
|
||||
```
|
||||
|
||||
## Configuration Customization
|
||||
|
||||
Each configuration file can be customized for your project:
|
||||
|
||||
1. **Adjust severity levels**: Change error levels to match your team's standards
|
||||
2. **Add ignore patterns**: Exclude specific files or directories
|
||||
3. **Enable/disable rules**: Fine-tune which checks are active
|
||||
4. **Set code style preferences**: Modify indentation, line length, etc.
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
These configurations include security-focused rules:
|
||||
|
||||
- **PHP**: Forbidden functions (eval, create_function)
|
||||
- **JavaScript**: No console.log in production
|
||||
- **Python**: Import security patterns
|
||||
- **HTML**: XSS prevention patterns
|
||||
|
||||
## CI/CD Integration
|
||||
|
||||
These tools work seamlessly with:
|
||||
|
||||
- GitHub Actions (see workflow templates)
|
||||
- GitLab CI
|
||||
- Jenkins
|
||||
- CircleCI
|
||||
- Travis CI
|
||||
|
||||
## Support and Updates
|
||||
|
||||
Configuration templates are maintained in the mokocli repository:
|
||||
- **Repository**: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
- **Documentation**: https://git.mokoconsulting.tech/MokoConsulting/mokocli/tree/main/docs
|
||||
- **Issues**: Report problems or suggest improvements via GitHub Issues
|
||||
|
||||
## Version History
|
||||
|
||||
- **v1.0.0** (2026-01): Initial release with PHP, JavaScript, Python, and HTML configurations
|
||||
@@ -1,55 +0,0 @@
|
||||
{
|
||||
"name": "mokoconsulting-tech/{{repo_name_lower}}",
|
||||
"description": "{{repo_name}} Dolibarr module by Moko Consulting",
|
||||
"type": "dolibarr-module",
|
||||
"version": "01.00.00",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Moko Consulting",
|
||||
"email": "hello@mokoconsulting.tech"
|
||||
}
|
||||
],
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
"require": {
|
||||
"php": ">=8.1",
|
||||
"mokoconsulting-tech/enterprise": "dev-version/04.02.00"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^10.5",
|
||||
"phpstan/phpstan": "^2.0",
|
||||
"squizlabs/php_codesniffer": "^4.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"MokoConsulting\\{{repo_name}}\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"MokoConsulting\\{{repo_name}}\\Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mokoconsulting.tech/mokoconsulting-tech/MokoCli-API"
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"sort-packages": true,
|
||||
"optimize-autoloader": true,
|
||||
"preferred-install": "dist",
|
||||
"allow-plugins": {
|
||||
"composer/installers": true
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"validate-module": "vendor/bin/validate-module --path .",
|
||||
"build": "vendor/bin/build-package --path .",
|
||||
"test": "phpunit",
|
||||
"phpcs": "phpcs --standard=vendor/mokoconsulting-tech/enterprise/phpcs.xml src/",
|
||||
"phpstan": "phpstan analyse -c phpstan.neon src/"
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
{
|
||||
"name": "mokoconsulting-tech/{{repo_name_lower}}",
|
||||
"description": "{{repo_name}} library by Moko Consulting",
|
||||
"type": "library",
|
||||
"version": "01.00.00",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Moko Consulting",
|
||||
"email": "hello@mokoconsulting.tech"
|
||||
}
|
||||
],
|
||||
"minimum-stability": "stable",
|
||||
"prefer-stable": true,
|
||||
"require": {
|
||||
"php": ">=8.1",
|
||||
"mokoconsulting-tech/enterprise": "dev-version/04.02.00"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^10.5",
|
||||
"phpstan/phpstan": "^2.0",
|
||||
"squizlabs/php_codesniffer": "^4.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"MokoConsulting\\{{repo_name}}\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"MokoConsulting\\{{repo_name}}\\Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mokoconsulting.tech/mokoconsulting-tech/MokoCli-API"
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"sort-packages": true,
|
||||
"optimize-autoloader": true,
|
||||
"preferred-install": "dist"
|
||||
},
|
||||
"scripts": {
|
||||
"validate": "vendor/bin/validate-structure --path .",
|
||||
"test": "phpunit",
|
||||
"phpcs": "phpcs --standard=vendor/mokoconsulting-tech/enterprise/phpcs.xml src/",
|
||||
"phpstan": "phpstan analyse -c vendor/mokoconsulting-tech/enterprise/phpstan.neon src/"
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
{
|
||||
"name": "mokoconsulting-tech/{{repo_name_lower}}",
|
||||
"description": "{{repo_name}} Joomla component by Moko Consulting",
|
||||
"type": "joomla-component",
|
||||
"version": "01.00.00",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Moko Consulting",
|
||||
"email": "hello@mokoconsulting.tech"
|
||||
}
|
||||
],
|
||||
"minimum-stability": "stable",
|
||||
"prefer-stable": true,
|
||||
"require": {
|
||||
"php": ">=8.1",
|
||||
"mokoconsulting-tech/enterprise": "dev-version/04.02.00"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^10.5",
|
||||
"phpstan/phpstan": "^2.0",
|
||||
"squizlabs/php_codesniffer": "^4.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"MokoConsulting\\{{repo_name}}\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"MokoConsulting\\{{repo_name}}\\Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mokoconsulting.tech/mokoconsulting-tech/MokoCli-API"
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"sort-packages": true,
|
||||
"optimize-autoloader": true,
|
||||
"preferred-install": "dist",
|
||||
"allow-plugins": {
|
||||
"composer/installers": true
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"validate-manifest": "vendor/bin/validate-manifest --path .",
|
||||
"build": "vendor/bin/build-package --path .",
|
||||
"test": "phpunit",
|
||||
"phpcs": "phpcs --standard=vendor/mokoconsulting-tech/enterprise/phpcs.xml src/",
|
||||
"phpstan": "phpstan analyse -c phpstan.neon src/"
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
# .ftpignore — FTP/SFTP upload exclusion rules
|
||||
# Syntax mirrors .gitignore: blank lines and # comments are ignored,
|
||||
# * matches within a path segment, ** matches across segments, ? matches one char.
|
||||
# A leading / anchors to the upload root; a trailing / matches directories only.
|
||||
# Negation (!) is not supported.
|
||||
#
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# ── Version-control metadata ──────────────────────────────────────────────────
|
||||
.git/
|
||||
.gitignore
|
||||
.gitkeep
|
||||
.gitattributes
|
||||
.gitmodules
|
||||
|
||||
# ── CI / editor / tooling artefacts ──────────────────────────────────────────
|
||||
.github/
|
||||
.editorconfig
|
||||
.yamllint
|
||||
.phpcs.xml
|
||||
.phpstan.neon
|
||||
.psalm.xml
|
||||
.mokostandards
|
||||
|
||||
# ── Dependency directories ────────────────────────────────────────────────────
|
||||
vendor/
|
||||
node_modules/
|
||||
|
||||
# ── Build / cache / temp ──────────────────────────────────────────────────────
|
||||
build/
|
||||
dist/
|
||||
*.log
|
||||
*.tmp
|
||||
*.cache
|
||||
|
||||
# ── Secrets & local config (HARDCODED DENY — never deploy these) ─────────────
|
||||
.env
|
||||
.env.*
|
||||
sftp-config*.json
|
||||
sftp-config.json.template
|
||||
scripts/sftp-config/
|
||||
scripts/keys/
|
||||
*.ppk
|
||||
*.pem
|
||||
*.key
|
||||
.ftpignore
|
||||
@@ -1,208 +0,0 @@
|
||||
# ============================================================
|
||||
# Local task tracking (not version controlled)
|
||||
# ============================================================
|
||||
TODO.md
|
||||
|
||||
# ============================================================
|
||||
# Environment and secrets
|
||||
# ============================================================
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
*.local.php
|
||||
*.secret.php
|
||||
configuration.php
|
||||
configuration.*.php
|
||||
configuration.local.php
|
||||
conf/conf.php
|
||||
conf/conf*.php
|
||||
secrets/
|
||||
*.secrets.*
|
||||
|
||||
# ============================================================
|
||||
# Logs, dumps and databases
|
||||
# ============================================================
|
||||
*.db
|
||||
*.db-journal
|
||||
*.dump
|
||||
*.log
|
||||
*.pid
|
||||
*.seed
|
||||
|
||||
|
||||
# ============================================================
|
||||
# OS / Editor / IDE cruft
|
||||
# ============================================================
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
desktop.ini
|
||||
Thumbs.db:encryptable
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
$RECYCLE.BIN/
|
||||
System Volume Information/
|
||||
*.lnk
|
||||
Icon?
|
||||
.idea/
|
||||
.settings/
|
||||
.claude/
|
||||
.claude-worktree*/
|
||||
.vscode/*
|
||||
!.vscode/tasks.json
|
||||
!.vscode/settings.json.example
|
||||
!.vscode/extensions.json
|
||||
*.code-workspace
|
||||
*.sublime*
|
||||
.project
|
||||
.buildpath
|
||||
.classpath
|
||||
*.bak
|
||||
*.swp
|
||||
*.swo
|
||||
*.tmp
|
||||
*.old
|
||||
*.orig
|
||||
|
||||
# ============================================================
|
||||
# Dev scripts and scratch
|
||||
# ============================================================
|
||||
TODO.md
|
||||
todo*
|
||||
*ffs*
|
||||
|
||||
# ============================================================
|
||||
# SFTP / sync tools
|
||||
# ============================================================
|
||||
sftp-config*.json
|
||||
sftp-config.json.template
|
||||
sftp-settings.json
|
||||
|
||||
# ============================================================
|
||||
# Sublime SFTP / FTP sync
|
||||
# ============================================================
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
*.sublime-settings
|
||||
.libsass.json
|
||||
*.ffs*
|
||||
|
||||
# ============================================================
|
||||
# Replit / cloud IDE
|
||||
# ============================================================
|
||||
.replit
|
||||
replit.md
|
||||
|
||||
# ============================================================
|
||||
# Archives / release artifacts
|
||||
# ============================================================
|
||||
*.7z
|
||||
*.rar
|
||||
*.tar
|
||||
*.tar.gz
|
||||
*.tgz
|
||||
*.zip
|
||||
artifacts/
|
||||
release/
|
||||
releases/
|
||||
|
||||
# ============================================================
|
||||
# Build outputs and site generators
|
||||
# ============================================================
|
||||
.mkdocs-build/
|
||||
.cache/
|
||||
.parcel-cache/
|
||||
build/
|
||||
dist/
|
||||
out/
|
||||
/site/
|
||||
*.map
|
||||
*.css.map
|
||||
*.js.map
|
||||
*.tsbuildinfo
|
||||
|
||||
# ============================================================
|
||||
# CI / test artifacts
|
||||
# ============================================================
|
||||
.coverage
|
||||
.coverage.*
|
||||
coverage/
|
||||
coverage.xml
|
||||
htmlcov/
|
||||
junit.xml
|
||||
reports/
|
||||
test-results/
|
||||
tests/_output/
|
||||
.github/local/
|
||||
.github/workflows/*.log
|
||||
|
||||
# ============================================================
|
||||
# Node / JavaScript
|
||||
# ============================================================
|
||||
node_modules/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
.pnpm-store/
|
||||
.yarn/
|
||||
.npmrc
|
||||
.eslintcache
|
||||
package-lock.json
|
||||
|
||||
# ============================================================
|
||||
# PHP / Composer tooling
|
||||
# ============================================================
|
||||
/vendor/
|
||||
!src/media/vendor/
|
||||
composer.lock
|
||||
*.phar
|
||||
codeception.phar
|
||||
.phpunit.result.cache
|
||||
.php_cs.cache
|
||||
.php-cs-fixer.cache
|
||||
.phpstan.cache
|
||||
.phplint-cache
|
||||
phpmd-cache/
|
||||
.psalm/
|
||||
.rector/
|
||||
|
||||
# ============================================================
|
||||
# Python
|
||||
# ============================================================
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*.pyc
|
||||
*$py.class
|
||||
*.so
|
||||
.Python
|
||||
.eggs/
|
||||
*.egg
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
MANIFEST
|
||||
develop-eggs/
|
||||
downloads/
|
||||
eggs/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
ENV/
|
||||
env/
|
||||
.venv/
|
||||
venv/
|
||||
.pytest_cache/
|
||||
.mypy_cache/
|
||||
.ruff_cache/
|
||||
.pyright/
|
||||
.tox/
|
||||
.nox/
|
||||
*.cover
|
||||
*.coverage
|
||||
hypothesis/
|
||||
|
||||
# ============================================================
|
||||
# Local wiki clone (not version controlled)
|
||||
# ============================================================
|
||||
wiki/
|
||||
|
||||
@@ -1,225 +0,0 @@
|
||||
# ============================================================
|
||||
# Local task tracking (not version controlled)
|
||||
# ============================================================
|
||||
TODO.md
|
||||
|
||||
# ============================================================
|
||||
# Environment and secrets
|
||||
# ============================================================
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
*.local.php
|
||||
*.secret.php
|
||||
configuration.php
|
||||
configuration.*.php
|
||||
configuration.local.php
|
||||
conf/conf.php
|
||||
conf/conf*.php
|
||||
secrets/
|
||||
*.secrets.*
|
||||
|
||||
# ============================================================
|
||||
# Logs, dumps and databases
|
||||
# ============================================================
|
||||
*.db
|
||||
*.db-journal
|
||||
*.dump
|
||||
*.log
|
||||
*.pid
|
||||
*.seed
|
||||
|
||||
|
||||
# ============================================================
|
||||
# OS / Editor / IDE cruft
|
||||
# ============================================================
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
desktop.ini
|
||||
Thumbs.db:encryptable
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
$RECYCLE.BIN/
|
||||
System Volume Information/
|
||||
*.lnk
|
||||
Icon?
|
||||
.idea/
|
||||
.settings/
|
||||
.claude/
|
||||
.claude-worktree*/
|
||||
.vscode/*
|
||||
!.vscode/tasks.json
|
||||
!.vscode/settings.json.example
|
||||
!.vscode/extensions.json
|
||||
*.code-workspace
|
||||
*.sublime*
|
||||
.project
|
||||
.buildpath
|
||||
.classpath
|
||||
*.bak
|
||||
*.swp
|
||||
*.swo
|
||||
*.tmp
|
||||
*.old
|
||||
*.orig
|
||||
|
||||
# ============================================================
|
||||
# Dev scripts and scratch
|
||||
# ============================================================
|
||||
TODO.md
|
||||
todo*
|
||||
*ffs*
|
||||
|
||||
# ============================================================
|
||||
# SFTP / sync tools
|
||||
# ============================================================
|
||||
sftp-config*.json
|
||||
sftp-config.json.template
|
||||
sftp-settings.json
|
||||
|
||||
# ============================================================
|
||||
# Sublime SFTP / FTP sync
|
||||
# ============================================================
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
*.sublime-settings
|
||||
.libsass.json
|
||||
*.ffs*
|
||||
|
||||
# ============================================================
|
||||
# Replit / cloud IDE
|
||||
# ============================================================
|
||||
.replit
|
||||
replit.md
|
||||
|
||||
# ============================================================
|
||||
# Archives / release artifacts
|
||||
# ============================================================
|
||||
*.7z
|
||||
*.rar
|
||||
*.tar
|
||||
*.tar.gz
|
||||
*.tgz
|
||||
*.zip
|
||||
artifacts/
|
||||
release/
|
||||
releases/
|
||||
|
||||
# ============================================================
|
||||
# Build outputs and site generators
|
||||
# ============================================================
|
||||
.mkdocs-build/
|
||||
.cache/
|
||||
.parcel-cache/
|
||||
build/
|
||||
dist/
|
||||
out/
|
||||
site/
|
||||
*.map
|
||||
*.css.map
|
||||
*.js.map
|
||||
*.tsbuildinfo
|
||||
|
||||
# ============================================================
|
||||
# CI / test artifacts
|
||||
# ============================================================
|
||||
.coverage
|
||||
.coverage.*
|
||||
coverage/
|
||||
coverage.xml
|
||||
htmlcov/
|
||||
junit.xml
|
||||
reports/
|
||||
test-results/
|
||||
tests/_output/
|
||||
.github/local/
|
||||
.github/workflows/*.log
|
||||
|
||||
# ============================================================
|
||||
# Node / JavaScript
|
||||
# ============================================================
|
||||
node_modules/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
.pnpm-store/
|
||||
.yarn/
|
||||
.npmrc
|
||||
.eslintcache
|
||||
package-lock.json
|
||||
|
||||
# ============================================================
|
||||
# PHP / Composer tooling
|
||||
# ============================================================
|
||||
/vendor/
|
||||
!src/media/vendor/
|
||||
composer.lock
|
||||
*.phar
|
||||
codeception.phar
|
||||
.phpunit.result.cache
|
||||
.php_cs.cache
|
||||
.php-cs-fixer.cache
|
||||
.phpstan.cache
|
||||
.phplint-cache
|
||||
phpmd-cache/
|
||||
.psalm/
|
||||
.rector/
|
||||
|
||||
# ============================================================
|
||||
# Python
|
||||
# ============================================================
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*.pyc
|
||||
*$py.class
|
||||
*.so
|
||||
.Python
|
||||
.eggs/
|
||||
*.egg
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
MANIFEST
|
||||
develop-eggs/
|
||||
downloads/
|
||||
eggs/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
ENV/
|
||||
env/
|
||||
.venv/
|
||||
venv/
|
||||
.pytest_cache/
|
||||
.mypy_cache/
|
||||
.ruff_cache/
|
||||
.pyright/
|
||||
.tox/
|
||||
.nox/
|
||||
*.cover
|
||||
*.coverage
|
||||
hypothesis/
|
||||
|
||||
# ============================================================
|
||||
# Local wiki clone (not version controlled)
|
||||
# ============================================================
|
||||
wiki/
|
||||
|
||||
# ============================================================
|
||||
# Dolibarr runtime / data
|
||||
# ============================================================
|
||||
documents/
|
||||
dolibarr_documents/
|
||||
uploads/
|
||||
thumbs/
|
||||
data/
|
||||
cache/
|
||||
temp/
|
||||
tmp/
|
||||
logs/
|
||||
htdocs/documents/
|
||||
htdocs/cache/
|
||||
htdocs/tmp/
|
||||
htdocs/logs/
|
||||
conf/conf.php
|
||||
@@ -1,43 +0,0 @@
|
||||
<!--
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
FILE INFORMATION
|
||||
DEFGROUP: MokoPlatform.Index
|
||||
INGROUP: MokoPlatform.Templates.Configs
|
||||
REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
PATH: /templates/configs/index.md
|
||||
BRIEF: Configuration templates directory index
|
||||
-->
|
||||
|
||||
# Code Quality Configuration Templates
|
||||
|
||||
Standardized configuration files for code quality and security tools.
|
||||
|
||||
## Available Configurations
|
||||
|
||||
### PHP
|
||||
- `phpcs.xml` - PHP_CodeSniffer (PSR-12)
|
||||
- `phpstan.neon` - PHPStan static analysis
|
||||
- `psalm.xml` - Psalm advanced analysis
|
||||
|
||||
### JavaScript/TypeScript
|
||||
- `.eslintrc.json` - ESLint linting
|
||||
- `.prettierrc.json` - Prettier formatting
|
||||
|
||||
### Python
|
||||
- `.pylintrc` - Pylint analysis
|
||||
- `pyproject.toml` - Black, isort, mypy, pytest
|
||||
|
||||
### HTML
|
||||
- `.htmlhintrc` - HTMLHint validation
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Copy configuration for your language
|
||||
cp templates/configs/.eslintrc.json .
|
||||
cp templates/configs/phpcs.xml .
|
||||
cp templates/configs/.pylintrc .
|
||||
```
|
||||
|
||||
See [README.md](README.md) for detailed documentation.
|
||||
@@ -1,38 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
FILE INFORMATION
|
||||
DEFGROUP: MokoPlatform.Templates.Config
|
||||
INGROUP: MokoPlatform.Templates
|
||||
REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
PATH: /templates/configs/manifest.xml.template
|
||||
BRIEF: XML manifest template — synced to .mokogitea/manifest.xml in every governed repository
|
||||
NOTE: This template is a reference only. The bulk sync generates XML via MokoCliParser::generate().
|
||||
|
||||
mokocli Repository Manifest
|
||||
Auto-generated by mokocli bulk sync.
|
||||
Manual edits to <governance> and <last-synced> may be overwritten.
|
||||
See: docs/standards/manifest-file-spec.md
|
||||
-->
|
||||
<mokocli xmlns="https://standards.mokoconsulting.tech/mokocli/1.0"
|
||||
schema-version="1.0">
|
||||
|
||||
<identity>
|
||||
<name>{{REPO_NAME}}</name>
|
||||
<org>{{org}}</org>
|
||||
<description>{{REPO_DESCRIPTION}}</description>
|
||||
<license spdx="GPL-3.0-or-later">GNU General Public License v3</license>
|
||||
</identity>
|
||||
|
||||
<governance>
|
||||
<platform>{{platform}}</platform>
|
||||
<standards-version>{{standards_version}}</standards-version>
|
||||
<standards-source>https://git.mokoconsulting.tech/MokoConsulting/mokocli</standards-source>
|
||||
</governance>
|
||||
|
||||
<build>
|
||||
<language>{{PRIMARY_LANGUAGE}}</language>
|
||||
</build>
|
||||
|
||||
</mokocli>
|
||||
@@ -1,19 +0,0 @@
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: MokoPlatform.Templates.Config
|
||||
# INGROUP: MokoPlatform.Templates
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
# PATH: /templates/configs/manifest.yml.template
|
||||
# BRIEF: Governance attachment template — synced to .mokogitea/manifest.xml in every governed repository
|
||||
# NOTE: Tokens replaced at sync time: {{org}}, {{repo_name}}, {{platform}}, {{standards_version}}
|
||||
#
|
||||
# This file is managed automatically by mokocli bulk sync.
|
||||
# Do not edit manually — changes will be overwritten on the next sync.
|
||||
# To update governance settings, open a PR in mokocli instead:
|
||||
# https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
|
||||
standards_source: "https://git.mokoconsulting.tech/MokoConsulting/mokocli"
|
||||
standards_version: "{{standards_version}}"
|
||||
platform: "{{platform}}"
|
||||
governed_repo: "{{org}}/{{repo_name}}"
|
||||
@@ -1,38 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
FILE INFORMATION
|
||||
DEFGROUP: MokoPlatform.Templates.Config
|
||||
INGROUP: MokoPlatform.Templates
|
||||
REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
PATH: /templates/configs/manifest.xml.template
|
||||
BRIEF: XML manifest template — synced to .mokogitea/manifest.xml in every governed repository
|
||||
NOTE: This template is a reference only. The bulk sync generates XML via MokoCliParser::generate().
|
||||
|
||||
mokocli Repository Manifest
|
||||
Auto-generated by mokocli bulk sync.
|
||||
Manual edits to <governance> and <last-synced> may be overwritten.
|
||||
See: docs/standards/manifest-file-spec.md
|
||||
-->
|
||||
<mokocli xmlns="https://git.mokoconsulting.tech/MokoConsulting/mokocli"
|
||||
schema-version="1.0">
|
||||
|
||||
<identity>
|
||||
<name>{{REPO_NAME}}</name>
|
||||
<org>{{org}}</org>
|
||||
<description>{{REPO_DESCRIPTION}}</description>
|
||||
<license spdx="GPL-3.0-or-later">GNU General Public License v3</license>
|
||||
</identity>
|
||||
|
||||
<governance>
|
||||
<platform>{{platform}}</platform>
|
||||
<standards-version>{{standards_version}}</standards-version>
|
||||
<standards-source>https://git.mokoconsulting.tech/MokoConsulting/mokocli</standards-source>
|
||||
</governance>
|
||||
|
||||
<build>
|
||||
<language>{{PRIMARY_LANGUAGE}}</language>
|
||||
</build>
|
||||
|
||||
</mokocli>
|
||||
@@ -1,19 +0,0 @@
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: MokoPlatform.Templates.Config
|
||||
# INGROUP: MokoPlatform.Templates
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
# PATH: /templates/configs/moko-standards.yml.template
|
||||
# BRIEF: Governance attachment template — synced to .mokostandards in every governed repository
|
||||
# NOTE: Tokens replaced at sync time: {{org}}, {{repo_name}}, {{platform}}, {{standards_version}}
|
||||
#
|
||||
# This file is managed automatically by mokocli bulk sync.
|
||||
# Do not edit manually — changes will be overwritten on the next sync.
|
||||
# To update governance settings, open a PR in mokocli instead:
|
||||
# https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
|
||||
standards_source: "https://git.mokoconsulting.tech/MokoConsulting/mokocli"
|
||||
standards_version: "{{standards_version}}"
|
||||
platform: "{{platform}}"
|
||||
governed_repo: "{{org}}/{{repo_name}}"
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"defaults": {
|
||||
"standard": "WCAG2AA",
|
||||
"timeout": 30000,
|
||||
"wait": 1000,
|
||||
"ignore": [],
|
||||
"chromeLaunchConfig": {
|
||||
"args": [
|
||||
"--no-sandbox",
|
||||
"--disable-setuid-sandbox"
|
||||
]
|
||||
}
|
||||
},
|
||||
"urls": [
|
||||
{
|
||||
"url": "http://localhost:8080/",
|
||||
"actions": []
|
||||
}
|
||||
],
|
||||
"concurrency": 2,
|
||||
"useIncognitoBrowserContext": true
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
-->
|
||||
<ruleset name="mokocli PHP Coding Standards">
|
||||
<description>PHP_CodeSniffer configuration for mokocli projects</description>
|
||||
|
||||
<!-- Files to check -->
|
||||
<file>src</file>
|
||||
<file>tests</file>
|
||||
|
||||
<!-- Exclude vendor and other dependencies -->
|
||||
<exclude-pattern>*/vendor/*</exclude-pattern>
|
||||
<exclude-pattern>*/node_modules/*</exclude-pattern>
|
||||
<exclude-pattern>*/.git/*</exclude-pattern>
|
||||
|
||||
<!-- Use PSR-12 as base standard -->
|
||||
<rule ref="PSR12"/>
|
||||
|
||||
<!-- Additional rules -->
|
||||
<rule ref="Generic.Arrays.DisallowLongArraySyntax"/>
|
||||
<rule ref="Generic.CodeAnalysis.EmptyStatement"/>
|
||||
<rule ref="Generic.CodeAnalysis.UnconditionalIfStatement"/>
|
||||
<rule ref="Generic.CodeAnalysis.UnnecessaryFinalModifier"/>
|
||||
<rule ref="Generic.Files.LineLength">
|
||||
<properties>
|
||||
<property name="lineLimit" value="120"/>
|
||||
<property name="absoluteLineLimit" value="150"/>
|
||||
</properties>
|
||||
</rule>
|
||||
<rule ref="Generic.PHP.ForbiddenFunctions">
|
||||
<properties>
|
||||
<property name="forbiddenFunctions" type="array">
|
||||
<element key="eval" value="null"/>
|
||||
<element key="create_function" value="null"/>
|
||||
<element key="var_dump" value="null"/>
|
||||
<element key="print_r" value="null"/>
|
||||
</property>
|
||||
</properties>
|
||||
</rule>
|
||||
<rule ref="Squiz.PHP.CommentedOutCode"/>
|
||||
<rule ref="Squiz.WhiteSpace.SuperfluousWhitespace"/>
|
||||
|
||||
<!-- Show progress and use colors -->
|
||||
<arg value="p"/>
|
||||
<arg name="colors"/>
|
||||
|
||||
<!-- Show sniff codes in all reports -->
|
||||
<arg value="s"/>
|
||||
</ruleset>
|
||||
@@ -1,39 +0,0 @@
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# PHPStan configuration for Dolibarr module repositories.
|
||||
# Extends the base MokoCli config and adds Dolibarr class stubs
|
||||
# so PHPStan can resolve CommonObject, DoliDB, Conf, User, etc.
|
||||
# without requiring a full Dolibarr installation.
|
||||
|
||||
parameters:
|
||||
level: 5
|
||||
|
||||
paths:
|
||||
- src
|
||||
|
||||
excludePaths:
|
||||
- vendor
|
||||
- node_modules
|
||||
|
||||
# Dolibarr class stubs — resolved via the enterprise package from vendor/
|
||||
stubFiles:
|
||||
- vendor/mokoconsulting-tech/enterprise/templates/stubs/dolibarr.php
|
||||
|
||||
# Suppress errors that are structural in Dolibarr's dynamic architecture
|
||||
ignoreErrors:
|
||||
# Dolibarr uses dynamic properties heavily (pre-PHP 8.2 pattern)
|
||||
- '#Access to an undefined property [A-Za-z]+::\$#'
|
||||
# Module descriptors use magic property assignment in __construct
|
||||
- '#Variable \$[a-z]+ might not be defined\.#'
|
||||
|
||||
# Common Dolibarr globals declared at script entry point
|
||||
dynamicConstantNames:
|
||||
- DOL_DOCUMENT_ROOT
|
||||
- DOL_URL_ROOT
|
||||
- DOL_VERSION
|
||||
- MAIN_DB_PREFIX
|
||||
|
||||
reportUnmatchedIgnoredErrors: false
|
||||
checkMissingIterableValueType: false
|
||||
checkGenericClassInNonGenericObjectType: false
|
||||
@@ -1,32 +0,0 @@
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# PHPStan configuration for Joomla extension repositories.
|
||||
# Extends the base MokoCli config and adds Joomla framework class stubs
|
||||
# so PHPStan can resolve Factory, CMSApplication, User, Table, etc.
|
||||
# without requiring a full Joomla installation.
|
||||
|
||||
parameters:
|
||||
level: 5
|
||||
|
||||
paths:
|
||||
- src
|
||||
|
||||
excludePaths:
|
||||
- vendor
|
||||
- node_modules
|
||||
|
||||
# Joomla framework stubs — resolved via the enterprise package from vendor/
|
||||
stubFiles:
|
||||
- vendor/mokoconsulting-tech/enterprise/templates/stubs/joomla.php
|
||||
|
||||
# Suppress errors that are structural in Joomla's service-container architecture
|
||||
ignoreErrors:
|
||||
# Joomla's service-based dependency injection returns mixed from getApplication()
|
||||
- '#Cannot call method .+ on Joomla\\CMS\\Application\\CMSApplication\|null#'
|
||||
# Factory::getX() patterns are safe at runtime even when nullable in stubs
|
||||
- '#Call to static method [a-zA-Z]+\(\) on an interface#'
|
||||
|
||||
reportUnmatchedIgnoredErrors: false
|
||||
checkMissingIterableValueType: false
|
||||
checkGenericClassInNonGenericObjectType: false
|
||||
@@ -1,35 +0,0 @@
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
#
|
||||
# This file is part of a Moko Consulting project.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# PHPStan configuration for MokoCli projects
|
||||
parameters:
|
||||
level: 5
|
||||
paths:
|
||||
- src
|
||||
- tests
|
||||
excludePaths:
|
||||
- vendor
|
||||
- node_modules
|
||||
|
||||
# Report unknown classes and functions
|
||||
reportUnmatchedIgnoredErrors: false
|
||||
|
||||
# Check for dead code
|
||||
checkMissingIterableValueType: false
|
||||
checkGenericClassInNonGenericObjectType: false
|
||||
|
||||
# Additional checks
|
||||
checkAlwaysTrueCheckTypeFunctionCall: true
|
||||
checkAlwaysTrueInstanceof: true
|
||||
checkAlwaysTrueStrictComparison: true
|
||||
checkExplicitMixedMissingReturn: true
|
||||
checkFunctionNameCase: true
|
||||
checkInternalClassCaseSensitivity: true
|
||||
|
||||
# Ignore common patterns
|
||||
ignoreErrors:
|
||||
# Add project-specific ignores here
|
||||
# - '#Call to an undefined method#'
|
||||
@@ -1,34 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
-->
|
||||
<psalm
|
||||
errorLevel="4"
|
||||
resolveFromConfigFile="true"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="https://getpsalm.org/schema/config"
|
||||
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
||||
findUnusedBaselineEntry="true"
|
||||
findUnusedCode="false"
|
||||
>
|
||||
<projectFiles>
|
||||
<directory name="src" />
|
||||
<directory name="tests" />
|
||||
<ignoreFiles>
|
||||
<directory name="vendor" />
|
||||
<directory name="node_modules" />
|
||||
</ignoreFiles>
|
||||
</projectFiles>
|
||||
|
||||
<issueHandlers>
|
||||
<UnusedVariable>
|
||||
<errorLevel type="suppress">
|
||||
<directory name="tests" />
|
||||
</errorLevel>
|
||||
</UnusedVariable>
|
||||
</issueHandlers>
|
||||
</psalm>
|
||||
@@ -1,85 +0,0 @@
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
#
|
||||
# This file is part of a Moko Consulting project.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Python project configuration for MokoCli projects
|
||||
|
||||
[tool.black]
|
||||
line-length = 100
|
||||
target-version = ['py38', 'py39', 'py310', 'py311']
|
||||
include = '\.pyi?$'
|
||||
exclude = '''
|
||||
/(
|
||||
\.git
|
||||
| \.venv
|
||||
| venv
|
||||
| \.eggs
|
||||
| \.tox
|
||||
| build
|
||||
| dist
|
||||
| __pycache__
|
||||
| node_modules
|
||||
)/
|
||||
'''
|
||||
|
||||
[tool.isort]
|
||||
profile = "black"
|
||||
line_length = 100
|
||||
multi_line_output = 3
|
||||
include_trailing_comma = true
|
||||
force_grid_wrap = 0
|
||||
use_parentheses = true
|
||||
ensure_newline_before_comments = true
|
||||
|
||||
[tool.mypy]
|
||||
python_version = "3.8"
|
||||
warn_return_any = true
|
||||
warn_unused_configs = true
|
||||
disallow_untyped_defs = false
|
||||
disallow_incomplete_defs = false
|
||||
check_untyped_defs = true
|
||||
disallow_untyped_calls = false
|
||||
disallow_untyped_decorators = false
|
||||
no_implicit_optional = true
|
||||
warn_redundant_casts = true
|
||||
warn_unused_ignores = true
|
||||
warn_no_return = true
|
||||
warn_unreachable = true
|
||||
strict_equality = true
|
||||
ignore_missing_imports = true
|
||||
|
||||
[[tool.mypy.overrides]]
|
||||
module = "tests.*"
|
||||
disallow_untyped_defs = false
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
minversion = "6.0"
|
||||
addopts = "-ra -q --strict-markers"
|
||||
testpaths = [
|
||||
"tests",
|
||||
]
|
||||
python_files = "test_*.py"
|
||||
python_classes = "Test*"
|
||||
python_functions = "test_*"
|
||||
|
||||
[tool.coverage.run]
|
||||
source = ["src"]
|
||||
omit = [
|
||||
"*/tests/*",
|
||||
"*/__pycache__/*",
|
||||
"*/venv/*",
|
||||
"*/.venv/*",
|
||||
]
|
||||
|
||||
[tool.coverage.report]
|
||||
exclude_lines = [
|
||||
"pragma: no cover",
|
||||
"def __repr__",
|
||||
"raise AssertionError",
|
||||
"raise NotImplementedError",
|
||||
"if __name__ == .__main__.:",
|
||||
"if TYPE_CHECKING:",
|
||||
"@abstractmethod",
|
||||
]
|
||||
@@ -1,26 +0,0 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:recommended",
|
||||
"schedule:weekly",
|
||||
":disableDependencyDashboard"
|
||||
],
|
||||
"labels": ["dependencies"],
|
||||
"automerge": false,
|
||||
"platformAutomerge": false,
|
||||
"rangeStrategy": "bump",
|
||||
"packageRules": [
|
||||
{
|
||||
"matchUpdateTypes": ["patch"],
|
||||
"automerge": true
|
||||
},
|
||||
{
|
||||
"matchManagers": ["composer"],
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"matchManagers": ["npm"],
|
||||
"enabled": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
<!--
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
FILE INFORMATION
|
||||
DEFGROUP: MokoPlatform.Index
|
||||
INGROUP: MokoPlatform.Templates.Docs
|
||||
REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
PATH: /templates/docs/README.md
|
||||
BRIEF: Documentation templates README
|
||||
-->
|
||||
|
||||
# Documentation Templates
|
||||
|
||||
## Purpose
|
||||
|
||||
This directory contains governed documentation templates for the mokocli organization. These templates ensure consistency, completeness, and compliance across all documentation artifacts.
|
||||
|
||||
## Intended Use
|
||||
|
||||
Use these templates when:
|
||||
|
||||
- Creating new documentation files
|
||||
- Establishing documentation in new repositories
|
||||
- Ensuring compliance with documentation standards
|
||||
- Maintaining consistency across projects
|
||||
|
||||
## Instructions
|
||||
|
||||
### Template Categories
|
||||
|
||||
Templates are organized into two categories:
|
||||
|
||||
1. **Required Templates** - `/templates/docs/required/`
|
||||
- Mandatory documentation files for all repositories
|
||||
- Must be present and maintained
|
||||
- Subject to compliance review
|
||||
|
||||
2. **Extra Templates** - `/templates/docs/extra/`
|
||||
- Optional documentation files
|
||||
- Recommended for specific use cases
|
||||
- Enhance documentation quality
|
||||
|
||||
### Using Templates
|
||||
|
||||
To use a template:
|
||||
|
||||
1. Navigate to appropriate template category (required or extra)
|
||||
2. Copy the template file to your target location
|
||||
3. Rename the file removing the `template-` prefix
|
||||
4. Replace all placeholder content with actual information
|
||||
5. Complete all required fields
|
||||
6. Remove example sections or mark them explicitly as examples
|
||||
7. Follow the template instructions section
|
||||
8. Validate against Document Formatting Policy
|
||||
|
||||
### Template Maintenance
|
||||
|
||||
Templates are governed assets and must:
|
||||
|
||||
- Follow Document Formatting Policy requirements
|
||||
- Include all required sections for templates
|
||||
- Contain no production data
|
||||
- Use placeholder values only
|
||||
- Be reviewed per governance schedule
|
||||
- Have Project task entries
|
||||
|
||||
## Required Fields
|
||||
|
||||
When using templates, ensure these fields are completed:
|
||||
|
||||
- All section headers and content
|
||||
- Metadata fields specific to the document
|
||||
- Revision history
|
||||
- Purpose and scope statements
|
||||
- Responsibilities and governance rules (where applicable)
|
||||
|
||||
## Example Usage
|
||||
|
||||
### Creating a New Repository README
|
||||
|
||||
```bash
|
||||
# Copy template to target location
|
||||
cp /templates/docs/required/template-README.md /path/to/repo/README.md
|
||||
|
||||
# Edit the file
|
||||
# - Replace "[Repository Name]" with actual repository name
|
||||
# - Complete all sections
|
||||
# - Update metadata
|
||||
# - Customize content for your repository
|
||||
```
|
||||
|
||||
### Creating a New Policy Document
|
||||
|
||||
```bash
|
||||
# Use policy template structure
|
||||
# Follow /docs/policy/ examples
|
||||
# Ensure all mandatory policy sections included
|
||||
# Obtain required approvals per policy
|
||||
```
|
||||
|
||||
## Metadata
|
||||
|
||||
- **Document Type:** overview
|
||||
- **Document Subtype:** catalog
|
||||
- **Owner Role:** Documentation Owner
|
||||
- **Approval Required:** No
|
||||
- **Evidence Required:** Yes
|
||||
- **Review Cycle:** Annual
|
||||
- **Retention:** Indefinite
|
||||
- **Compliance Tags:** Governance
|
||||
- **Status:** Published
|
||||
|
||||
## Revision History
|
||||
|
||||
- Initial template catalog established
|
||||
- Template categories and usage instructions defined
|
||||
- Template maintenance requirements documented
|
||||
@@ -1,200 +0,0 @@
|
||||
<!--
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
FILE INFORMATION
|
||||
DEFGROUP: MokoPlatform.Index
|
||||
INGROUP: MokoPlatform.Templates.Docs.Extra
|
||||
REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
PATH: /templates/docs/extra/README.md
|
||||
BRIEF: Extra documentation templates README
|
||||
-->
|
||||
|
||||
# Extra Documentation Templates
|
||||
|
||||
## Purpose
|
||||
|
||||
This directory contains optional documentation templates that enhance repository documentation quality and completeness. These templates are recommended but not mandatory, providing additional documentation capabilities beyond baseline requirements.
|
||||
|
||||
## Intended Use
|
||||
|
||||
Use these templates when:
|
||||
|
||||
- Enhanced documentation is beneficial
|
||||
- Specific use cases require additional documentation
|
||||
- Improving documentation beyond minimum requirements
|
||||
- Addressing stakeholder needs for additional information
|
||||
- Meeting specific project or compliance needs
|
||||
|
||||
## Instructions
|
||||
|
||||
### Optional Templates
|
||||
|
||||
Extra templates provide documentation for:
|
||||
|
||||
1. **Code of Conduct** - Community behavior guidelines
|
||||
2. **Security Policy** - Security reporting and disclosure
|
||||
3. **Support Documentation** - Support channels and procedures
|
||||
4. **Governance Documents** - Decision-making and authority
|
||||
5. **Additional Technical Documentation** - Architecture, design, API docs
|
||||
|
||||
### Template Selection
|
||||
|
||||
Choose extra templates based on:
|
||||
|
||||
- **Project Size** - Larger projects benefit from comprehensive documentation
|
||||
- **Community Size** - Projects with external contributors need governance docs
|
||||
- **Security Requirements** - Security-sensitive projects need security policy
|
||||
- **Stakeholder Needs** - Specific stakeholder requirements
|
||||
- **Compliance Requirements** - Regulatory or audit requirements
|
||||
|
||||
### Template Usage
|
||||
|
||||
For each extra template:
|
||||
|
||||
1. Determine if template is needed for your project
|
||||
2. Copy the template file from this directory
|
||||
3. Rename removing the `template-` prefix
|
||||
4. Place in appropriate repository location
|
||||
5. Complete all sections
|
||||
6. Replace all placeholder values
|
||||
7. Customize for your project context
|
||||
8. Create Project task if document is critical
|
||||
9. Maintain per appropriate review cycle
|
||||
|
||||
### When to Use Extra Templates
|
||||
|
||||
#### Code of Conduct
|
||||
|
||||
Use when:
|
||||
|
||||
- Repository accepts external contributions
|
||||
- Community interactions expected
|
||||
- Need to establish behavioral expectations
|
||||
- Creating inclusive environment
|
||||
|
||||
#### Security Policy
|
||||
|
||||
Use when:
|
||||
|
||||
- Repository contains security-sensitive code
|
||||
- Security vulnerabilities may be discovered
|
||||
- Need coordinated disclosure process
|
||||
- Compliance requires security documentation
|
||||
|
||||
#### Support Documentation
|
||||
|
||||
Use when:
|
||||
|
||||
- Users need support information
|
||||
- Multiple support channels exist
|
||||
- Support expectations must be clear
|
||||
- SLA or support tiers defined
|
||||
|
||||
#### Governance Documents
|
||||
|
||||
Use when:
|
||||
|
||||
- Decision-making authority must be clear
|
||||
- Multiple maintainers or teams involved
|
||||
- Escalation procedures needed
|
||||
- Organizational governance required
|
||||
|
||||
## Required Fields
|
||||
|
||||
When using extra templates, ensure these fields are completed:
|
||||
|
||||
- All section headers with appropriate content
|
||||
- Purpose and scope clearly defined
|
||||
- Contact information where applicable
|
||||
- Procedures and processes clearly documented
|
||||
- Metadata (for governed documents)
|
||||
- Revision history
|
||||
|
||||
## Example Usage
|
||||
|
||||
### Adding Code of Conduct
|
||||
|
||||
```bash
|
||||
# Copy template
|
||||
cp /templates/docs/extra/template-CODE_OF_CONDUCT.md ./CODE_OF_CONDUCT.md
|
||||
|
||||
# Edit the file
|
||||
# - Complete all sections
|
||||
# - Add contact information for enforcement
|
||||
# - Customize behavioral expectations
|
||||
# - Add reporting procedures
|
||||
|
||||
# Commit to repository
|
||||
git add CODE_OF_CONDUCT.md
|
||||
git commit -m "Add Code of Conduct"
|
||||
```
|
||||
|
||||
### Adding Security Policy
|
||||
|
||||
```bash
|
||||
# Copy template
|
||||
cp /templates/docs/extra/template-SECURITY.md ./SECURITY.md
|
||||
|
||||
# Edit the file
|
||||
# - Define supported versions
|
||||
# - Add vulnerability reporting procedures
|
||||
# - Define disclosure timelines
|
||||
# - Add security contact information
|
||||
|
||||
# Commit to repository
|
||||
git add SECURITY.md
|
||||
git commit -m "Add security policy"
|
||||
```
|
||||
|
||||
### Adding Support Documentation
|
||||
|
||||
```bash
|
||||
# Copy template
|
||||
cp /templates/docs/extra/template-SUPPORT.md ./SUPPORT.md
|
||||
|
||||
# Edit the file
|
||||
# - List support channels
|
||||
# - Define response expectations
|
||||
# - Add support tiers if applicable
|
||||
# - Include escalation procedures
|
||||
|
||||
# Commit to repository
|
||||
git add SUPPORT.md
|
||||
git commit -m "Add support documentation"
|
||||
```
|
||||
|
||||
## Template List
|
||||
|
||||
- **template-CODE_OF_CONDUCT.md** - Community behavior guidelines template
|
||||
- Additional templates as needed for specific use cases
|
||||
|
||||
Note: Extra templates are created on-demand based on organizational needs. Check this directory for available templates or request new templates through governance channels.
|
||||
|
||||
## Best Practices
|
||||
|
||||
When using extra templates:
|
||||
|
||||
- Only use templates that add value to your project
|
||||
- Keep documentation current and accurate
|
||||
- Follow Document Formatting Policy
|
||||
- Create Project tasks for critical documents
|
||||
- Review and update per appropriate schedule
|
||||
- Remove unused templates to reduce maintenance burden
|
||||
|
||||
## Metadata
|
||||
|
||||
- **Document Type:** overview
|
||||
- **Document Subtype:** catalog
|
||||
- **Owner Role:** Documentation Owner
|
||||
- **Approval Required:** No
|
||||
- **Evidence Required:** Yes
|
||||
- **Review Cycle:** Annual
|
||||
- **Retention:** Indefinite
|
||||
- **Compliance Tags:** Governance
|
||||
- **Status:** Published
|
||||
|
||||
## Revision History
|
||||
|
||||
- Initial extra templates catalog established
|
||||
- Template selection guidance defined
|
||||
- Usage instructions and best practices documented
|
||||
@@ -1,32 +0,0 @@
|
||||
<!--
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
FILE INFORMATION
|
||||
DEFGROUP: MokoPlatform.Index
|
||||
INGROUP: MokoPlatform.Templates.Docs.Extra
|
||||
REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
||||
PATH: /templates/docs/extra/index.md
|
||||
BRIEF: Extra documentation templates directory index
|
||||
-->
|
||||
|
||||
# Docs Index: /templates/docs/extra
|
||||
|
||||
## Purpose
|
||||
|
||||
This index provides navigation to documentation within this folder.
|
||||
|
||||
## Documents
|
||||
|
||||
- [README](./README.md)
|
||||
- [template-CODE_OF_CONDUCT](./template-CODE_OF_CONDUCT.md)
|
||||
|
||||
## Metadata
|
||||
|
||||
- **Document Type:** index
|
||||
- **Auto-generated:** This file is automatically generated by rebuild_indexes.py
|
||||
|
||||
## Revision History
|
||||
|
||||
| Change | Notes | Author |
|
||||
| --- | --- | --- |
|
||||
| Automated update | Generated by documentation index automation | rebuild_indexes.py |
|
||||
@@ -1,86 +0,0 @@
|
||||
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License (./LICENSE.md).
|
||||
|
||||
# FILE INFORMATION
|
||||
DEFGROUP:
|
||||
INGROUP: Project.Documentation
|
||||
REPO:
|
||||
PATH: ./CODE_OF_CONDUCT.md
|
||||
BRIEF: Reference + packaging repo for Moko Consulting Developer GPT Other Default
|
||||
-->
|
||||
# Code of Conduct
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
The purpose of this Code of Conduct is to ensure a safe, inclusive, and respectful environment for all contributors and participants in Moko Consulting projects. This applies to all interactions, whether in repositories, issue trackers, documentation, meetings, or community spaces.
|
||||
|
||||
## 2. Our Standards
|
||||
|
||||
Participants are expected to uphold behaviors that strengthen our community, including:
|
||||
|
||||
Demonstrating empathy and respect toward others.
|
||||
Being inclusive of diverse viewpoints and backgrounds.
|
||||
Gracefully accepting constructive feedback.
|
||||
Prioritizing collaboration over conflict.
|
||||
Showing professionalism in all interactions.
|
||||
|
||||
### Unacceptable behavior includes:
|
||||
|
||||
Harassment, discrimination, or derogatory comments.
|
||||
Threatening or violent language or actions.
|
||||
Disruptive, aggressive, or intentionally harmful behavior.
|
||||
Publishing others’ private information without permission.
|
||||
Any behavior that violates applicable laws.
|
||||
|
||||
## 3. Responsibilities of Maintainers
|
||||
|
||||
Maintainers are responsible for:
|
||||
|
||||
Clarifying acceptable behavior.
|
||||
Taking appropriate corrective action when unacceptable behavior occurs.
|
||||
Removing, editing, or rejecting contributions that violate this Code.
|
||||
Temporarily or permanently banning contributors who engage in repeated or severe violations.
|
||||
|
||||
## 4. Scope
|
||||
|
||||
This Code applies to:
|
||||
|
||||
All Moko Consulting repositories.
|
||||
All documentation and collaboration platforms.
|
||||
Public and private communication related to project activities.
|
||||
Any representation of Moko Consulting in online or offline spaces.
|
||||
|
||||
## 5. Enforcement
|
||||
|
||||
Instances of misconduct may be reported to:
|
||||
**[hello@mokoconsulting.tech](mailto:hello@mokoconsulting.tech)**
|
||||
|
||||
All reports will be reviewed and investigated promptly and fairly. Maintainers are obligated to maintain confidentiality where possible.
|
||||
|
||||
Consequences may include:
|
||||
|
||||
A warning.
|
||||
Required training or mediation.
|
||||
Temporary or permanent bans.
|
||||
Escalation to legal authorities when required.
|
||||
|
||||
## 6. Acknowledgements
|
||||
|
||||
This Code of Conduct is inspired by widely adopted community guidelines, including the Contributor Covenant and major open-source collaboration standards.
|
||||
|
||||
## 7. Related Documents
|
||||
|
||||
[Governance Guide](./docs-governance.md)
|
||||
[Contributor Guide](./docs-contributing.md)
|
||||
[Documentation Index](./docs-index.md)
|
||||
|
||||
This Code of Conduct is a living document and may be updated following the established Change Management process.
|
||||
@@ -1,142 +0,0 @@
|
||||
<!--
|
||||
Copyright (C) 2026 [Organization Name] <contact@example.com>
|
||||
|
||||
This file is part of [Project Name].
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
# [Project Name] Roadmap
|
||||
|
||||
## Scope and Intent
|
||||
|
||||
This document defines the roadmap for [Project Name] starting with version **[X.Y.Z]**. It establishes the sequencing, intent, and maturity expectations for deliverables governed by this project.
|
||||
|
||||
This roadmap is forward-looking by design. Completed work prior to the current baseline version is considered foundational and is intentionally excluded. This file tracks **current and future-state development only**.
|
||||
|
||||
## Version [X.Y.Z] — [Phase Name] ✅ COMPLETED / 🔄 IN PROGRESS / 📋 PLANNED
|
||||
|
||||
Focus: [Brief description of this version's primary focus]
|
||||
|
||||
### Completed Deliverables
|
||||
|
||||
* ✅ **[Category Name]**
|
||||
* ✅ [Specific deliverable or feature]
|
||||
* ✅ [Specific deliverable or feature]
|
||||
* ✅ **[Category Name]**
|
||||
* ✅ [Specific deliverable or feature]
|
||||
|
||||
### In Progress
|
||||
|
||||
* 🔄 [Item currently being worked on]
|
||||
* 🔄 [Item currently being worked on]
|
||||
|
||||
### Planned Deliverables
|
||||
|
||||
* [Future planned item]
|
||||
* [Future planned item]
|
||||
|
||||
### Achieved Outcomes
|
||||
|
||||
* ✅ [Measurable outcome or benefit]
|
||||
* ✅ [Measurable outcome or benefit]
|
||||
* 🔄 [Partially achieved outcome]
|
||||
|
||||
## Version [X.Y+1.Z] — [Next Phase Name]
|
||||
|
||||
Focus: [Brief description of next version's primary focus]
|
||||
|
||||
### In-Scope Deliverables
|
||||
|
||||
* [Deliverable for next version]
|
||||
* [Deliverable for next version]
|
||||
|
||||
### Outcomes
|
||||
|
||||
* [Expected outcome or benefit]
|
||||
* [Expected outcome or benefit]
|
||||
|
||||
## Version [X.Y+2.Z] — [Future Phase Name]
|
||||
|
||||
Focus: [Brief description of future version's primary focus]
|
||||
|
||||
### Planned Deliverables
|
||||
|
||||
* [Future deliverable]
|
||||
* [Future deliverable]
|
||||
|
||||
### Outcomes
|
||||
|
||||
* [Expected outcome]
|
||||
* [Expected outcome]
|
||||
|
||||
## Version [X.Y+3.Z] and Beyond — [Long-term Vision]
|
||||
|
||||
Focus: [Long-term strategic direction]
|
||||
|
||||
### Forward-Looking Initiatives
|
||||
|
||||
* [Strategic initiative]
|
||||
* [Strategic initiative]
|
||||
|
||||
### Outcomes
|
||||
|
||||
* [Long-term goal]
|
||||
* [Long-term goal]
|
||||
|
||||
---
|
||||
|
||||
This roadmap is intentionally conservative and additive. New versions extend prior guarantees without breaking existing contracts.
|
||||
|
||||
## Guidelines for Version Planning
|
||||
|
||||
### Version Numbering
|
||||
|
||||
Use semantic versioning for clarity:
|
||||
- **Major versions** (X.0.0): Breaking changes, major architectural shifts
|
||||
- **Minor versions** (X.Y.0): New features, significant enhancements
|
||||
- **Patch versions** (X.Y.Z): Bug fixes, minor improvements
|
||||
|
||||
### Planning Horizon
|
||||
|
||||
- **Current Version**: Actively being delivered
|
||||
- **Next 2-3 Versions**: Clearly defined with specific deliverables
|
||||
- **Future Versions**: High-level themes and strategic direction
|
||||
|
||||
### Status Indicators
|
||||
|
||||
- ✅ **COMPLETED**: Delivered and validated
|
||||
- 🔄 **IN PROGRESS**: Active development underway
|
||||
- 📋 **PLANNED**: Scheduled but not yet started
|
||||
- ⏸️ **PAUSED**: Temporarily on hold
|
||||
- ❌ **CANCELLED**: No longer pursuing
|
||||
|
||||
## Metadata
|
||||
|
||||
```
|
||||
Owner: [Owner Name/Role]
|
||||
Reviewers: [Reviewer Names/Roles]
|
||||
Status: Active
|
||||
Last Updated: [YYYY-MM-DD]
|
||||
Next Review: [YYYY-MM-DD]
|
||||
```
|
||||
|
||||
## Revision History
|
||||
|
||||
| Date | Version | Author | Notes |
|
||||
| ---------- | -------- | -------------- | ------------------------------- |
|
||||
| YYYY-MM-DD | X.Y.Z | [Author Name] | [Description of changes] |
|
||||
| YYYY-MM-DD | X.Y.Z | [Author Name] | [Description of changes] |
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user