From 9edfeb6075697f7fc97130a0c9adeb74ed9c4c7f Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 09:28:19 +0000 Subject: [PATCH 01/28] chore: sync notify.yml from Template-Generic [skip ci] --- .mokogitea/workflows/notify.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.mokogitea/workflows/notify.yml b/.mokogitea/workflows/notify.yml index 5fead533f2..656996fbdc 100644 --- a/.mokogitea/workflows/notify.yml +++ b/.mokogitea/workflows/notify.yml @@ -46,13 +46,13 @@ jobs: WORKFLOW="${{ github.event.workflow_run.name }}" URL="${{ github.event.workflow_run.html_url }}" - curl -sS \ + curl -sS --retry 3 --retry-connrefused --retry-delay 2 --max-time 20 \ -H "Title: ${REPO} released" \ -H "Tags: white_check_mark,package" \ -H "Priority: default" \ -H "Click: ${URL}" \ -d "${WORKFLOW} completed successfully." \ - "${NTFY_URL}/${NTFY_TOPIC}" + "${NTFY_URL}/${NTFY_TOPIC}" || echo "::warning::ntfy notification could not be delivered (non-fatal)" - name: Notify on failure if: github.event.workflow_run.conclusion == 'failure' @@ -61,10 +61,10 @@ jobs: WORKFLOW="${{ github.event.workflow_run.name }}" URL="${{ github.event.workflow_run.html_url }}" - curl -sS \ + curl -sS --retry 3 --retry-connrefused --retry-delay 2 --max-time 20 \ -H "Title: ${REPO} workflow failed" \ -H "Tags: x,warning" \ -H "Priority: high" \ -H "Click: ${URL}" \ -d "${WORKFLOW} failed. Check the run for details." \ - "${NTFY_URL}/${NTFY_TOPIC}" + "${NTFY_URL}/${NTFY_TOPIC}" || echo "::warning::ntfy notification could not be delivered (non-fatal)" From 02c2033caa2b93fbc8180b07cc44c10bd9f9ae54 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 09:28:24 +0000 Subject: [PATCH 02/28] chore: sync pr-check.yml from Template-Generic [skip ci] --- .mokogitea/workflows/pr-check.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.mokogitea/workflows/pr-check.yml b/.mokogitea/workflows/pr-check.yml index c7c2e8f070..2874d60783 100644 --- a/.mokogitea/workflows/pr-check.yml +++ b/.mokogitea/workflows/pr-check.yml @@ -258,8 +258,9 @@ jobs: while IFS= read -r -d '' file; do # Skip vendor, node_modules, and index.html stub files case "$file" in ./vendor/*|./node_modules/*) continue ;; esac - # Check first 10 lines for JEXEC or JPATH guard - if ! head -20 "$file" | grep -qE "defined\s*\(\s*['\"](_JEXEC|JPATH_BASE|\\\\JPATH_PLATFORM)['\"]"; then + # Scan the whole file for the JEXEC/JPATH guard: it is placed after + # the SPDX/file-header docblock, which commonly runs past 20 lines. + if ! grep -qE "defined\s*\(\s*['\"](_JEXEC|JPATH_BASE|\\\\JPATH_PLATFORM)['\"]" "$file"; then echo "::error file=${file}::Missing JEXEC guard: ${file}" ERRORS=$((ERRORS + 1)) fi From 94e6030e58e7fd3b53f4ef2a0dda632a982ca260 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 15:28:50 +0000 Subject: [PATCH 03/28] chore: sync standards-compliance.yml from Template-Generic [skip ci] --- .mokogitea/workflows/standards-compliance.yml | 2614 +++++++++++++++++ 1 file changed, 2614 insertions(+) create mode 100644 .mokogitea/workflows/standards-compliance.yml diff --git a/.mokogitea/workflows/standards-compliance.yml b/.mokogitea/workflows/standards-compliance.yml new file mode 100644 index 0000000000..7048eab9a9 --- /dev/null +++ b/.mokogitea/workflows/standards-compliance.yml @@ -0,0 +1,2614 @@ +# Copyright (C) 2026 Moko Consulting +# SPDX-License-Identifier: GPL-3.0-or-later +# FILE INFORMATION +# DEFGROUP: GitHub.Workflow +# INGROUP: MokoStandards.Compliance +# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# PATH: /.mokogitea/workflows/standards-compliance.yml +# VERSION: 04.06.00 +# BRIEF: MokoStandards compliance validation workflow +# NOTE: Validates repository structure, documentation, and coding standards + +name: "Generic: Standards Compliance" + +# ╔════════════════════════════════════════════════════════════════════════╗ +# ║ MOKOSTANDARDS COMPLIANCE WORKFLOW ║ +# ╠════════════════════════════════════════════════════════════════════════╣ +# ║ ║ +# ║ 28 checks across 4 priority tiers: ║ +# ║ ║ +# ║ TIER 1 — CRITICAL (must pass) ║ +# ║ secret-scanning, license-compliance, repository-structure, ║ +# ║ coding-standards, version-consistency ║ +# ║ ║ +# ║ TIER 2 — IMPORTANT (should pass) ║ +# ║ workflow-validation, documentation-quality, readme-completeness, ║ +# ║ git-hygiene, script-integrity ║ +# ║ ║ +# ║ TIER 3 — QUALITY (code metrics) ║ +# ║ line-length, file-naming, insecure-patterns, complexity, ║ +# ║ duplication, dead-code ║ +# ║ ║ +# ║ TIER 4 — SUPPLEMENTARY (informational) ║ +# ║ file-size, binary, todo, deps, links, api-docs, accessibility, ║ +# ║ performance, enterprise, health, terraform ║ +# ║ ║ +# ║ File size: warning >15MB, critical >20MB ║ +# ║ Exempt: .mmdb, .woff2, .woff, .ttf, .otf ║ +# ║ ║ +# ╚════════════════════════════════════════════════════════════════════════╝ + +env: + WORKFLOW_VERSION: "04.04.01" + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +# MokoStandards Policy Compliance: +# - File formatting: Enforces organizational coding standards +# - Reference: docs/policy/file-formatting.md + +# ┌─────────────────────────────────────────────────────────────────────────┐ +# │ WORKFLOW FLOW DIAGRAM │ +# └─────────────────────────────────────────────────────────────────────────┘ +# +# TRIGGER: Push/PR to main/dev/rc branches +# │ +# ▼ +# ┌──────────────────────────────────────────────────────────────┐ +# │ PARALLEL VALIDATION CHECKS │ +# └──────────────────────────────────────────────────────────────┘ +# │ +# ├─────────────┬──────────────┬──────────────┬────────────┐ +# ▼ ▼ ▼ ▼ ▼ +# ┌─────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐ ┌──────────┐ +# │Repository │File Header │Code Style│ │ Docs │ │ License │ +# │Structure│ │ Validation│ │ Check │ │ Check │ │ Check │ +# └─────────┘ └──────────┘ └──────────┘ └─────────┘ └──────────┘ +# │ │ │ │ │ +# ▼ ▼ ▼ ▼ ▼ +# ┌─────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐ ┌──────────┐ +# │ Check │ │ Verify │ │ Run │ │ Check │ │ Verify │ +# │Required │ │Copyright │ │ Linters │ │README │ │SPDX-ID │ +# │ Dirs │ │ Header │ │(Python, │ │ Exists │ │ Present │ +# │ │ │ Format │ │PHP,YAML) │ │ │ │ │ +# └─────────┘ └──────────┘ └──────────┘ └─────────┘ └──────────┘ +# │ │ │ │ │ +# └─────────────┴──────────────┴──────────────┴────────────┘ +# │ +# ▼ +# ┌──────────────────┐ +# │ All Checks Pass?│ +# └──────────────────┘ +# │ │ +# YES │ │ NO +# ▼ ▼ +# ┌──────────┐ ┌──────────────┐ +# │ SUCCESS │ │ CREATE ISSUE │ +# │ Summary │ │ with Failure │ +# └──────────┘ │ Details │ +# └──────────────┘ + +on: + push: + branches: [main, dev/**, rc/**, version/**] + pull_request: + branches: [main, dev/**, rc/**] + workflow_dispatch: + +permissions: + contents: read + pull-requests: write + issues: write + +jobs: + # ════════════════════════════════════════════════════════════════════════ + # TIER 1 — CRITICAL (must pass, blocks merge) + # ════════════════════════════════════════════════════════════════════════ + secret-scanning: + name: Secret Scanning + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Scan for Secrets + run: | + set -x + echo "## 🔒 Secret Scanning" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "Scanning for hardcoded secrets and credentials." >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Define secret patterns + VIOLATIONS=0 + + # Check for common secret patterns + echo "### Secret Patterns" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Helper: scan with a pattern, show results with file:line, return count + scan_pattern() { + local label="$1" icon="$2" tmpfile="$3" + local count=0 + if [ -f "$tmpfile" ]; then + count=$(wc -l < "$tmpfile") + fi + if [ "$count" -gt 0 ]; then + echo "${icon} **${label}**: ${count} finding(s)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY + echo "View locations" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "| File | Line | Match |" >> $GITHUB_STEP_SUMMARY + echo "|------|------|-------|" >> $GITHUB_STEP_SUMMARY + head -20 "$tmpfile" | while IFS= read -r line; do + FILE=$(echo "$line" | cut -d: -f1 | sed 's|^\./||') + LINENO=$(echo "$line" | cut -d: -f2) + MATCH=$(echo "$line" | cut -d: -f3- | head -c 80 | sed 's/|/\\|/g') + echo "| \`${FILE}\` | ${LINENO} | \`${MATCH}\` |" >> $GITHUB_STEP_SUMMARY + done + if [ "$count" -gt 20 ]; then + echo "" >> $GITHUB_STEP_SUMMARY + echo "*... and $((count - 20)) more*" >> $GITHUB_STEP_SUMMARY + fi + echo "" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + VIOLATIONS=$((VIOLATIONS + count)) + fi + } + + # Pattern 1: password/secret assignments + grep -r -n -E "(password|passwd|pwd|secret|api[_-]?key|token).*=.*['\"]" . \ + --include="*.php" --include="*.py" --include="*.js" --include="*.ts" \ + --exclude-dir=".git" --exclude-dir="vendor" --exclude-dir="node_modules" 2>/dev/null | \ + grep -v -E '(test|example|sample|getenv|getString|getArgument|config\[|/\.\*/|^\s*//|^\s*\*|CREDENTIAL_PATTERNS|SecurityValidator|SECRET_PATTERN|===|!==|ApiClient|str_contains|gen_wrappers)' | \ + grep -v "= ''" | grep -v '= ""' | grep -v '\$this->config' | \ + grep -v 'type="password"' | grep -v 'type="text"' | grep -v 'name="password"' | grep -v 'name="secretkey"' | \ + grep -v '/dev/null > /tmp/secrets2.txt || true + scan_pattern "Private keys" "❌" /tmp/secrets2.txt + + # Pattern 3: AWS keys + grep -r -n -E "AKIA[0-9A-Z]{16}" . \ + --include="*.php" --include="*.py" --include="*.js" --include="*.txt" --include="*.env" \ + --exclude-dir=".git" --exclude-dir="vendor" --exclude-dir="node_modules" 2>/dev/null > /tmp/secrets3.txt || true + scan_pattern "AWS access keys" "❌" /tmp/secrets3.txt + + # Pattern 4: GitHub tokens + grep -r -n -E "gh[ps]_[a-zA-Z0-9]{36}" . \ + --include="*.php" --include="*.py" --include="*.js" --include="*.txt" --include="*.env" \ + --exclude-dir=".git" --exclude-dir="vendor" --exclude-dir="node_modules" 2>/dev/null > /tmp/secrets4.txt || true + scan_pattern "GitHub tokens" "❌" /tmp/secrets4.txt + + echo "" >> $GITHUB_STEP_SUMMARY + + if [ "$VIOLATIONS" -gt 0 ]; then + echo "**Total Violations**: $VIOLATIONS" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY + echo "View detected secrets (file paths only)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + cat /tmp/secrets*.txt 2>/dev/null | cut -d: -f1 | sort -u >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Action Required**: Remove hardcoded secrets immediately!" >> $GITHUB_STEP_SUMMARY + echo "Use environment variables or secrets management instead." >> $GITHUB_STEP_SUMMARY + exit 1 + else + echo "✅ No hardcoded secrets detected" >> $GITHUB_STEP_SUMMARY + fi + + license-compliance: + name: License Header Validation + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Check SPDX Headers + run: | + set -x + echo "### SPDX License Header Check" >> $GITHUB_STEP_SUMMARY + + # Count source files with and without SPDX headers + TOTAL_PHP=0 + WITH_SPDX_PHP=0 + + if find . -name "*.php" -type f ! -path "./vendor/*" | head -1 | grep -q .; then + TOTAL_PHP=$(find . -name "*.php" -type f ! -path "./vendor/*" | wc -l) + WITH_SPDX_PHP=$(find . -name "*.php" -type f ! -path "./vendor/*" -exec grep -l "SPDX-License-Identifier" {} \; | wc -l) + fi + + if [ "$TOTAL_PHP" -gt 0 ]; then + PERCENT=$((WITH_SPDX_PHP * 100 / TOTAL_PHP)) + echo "- PHP files: $WITH_SPDX_PHP/$TOTAL_PHP ($PERCENT%) with SPDX headers" >> $GITHUB_STEP_SUMMARY + + if [ "$PERCENT" -lt 80 ]; then + echo "⚠️ Less than 80% of PHP files have SPDX headers" >> $GITHUB_STEP_SUMMARY + else + echo "✅ Good SPDX header coverage" >> $GITHUB_STEP_SUMMARY + fi + fi + + - name: Validate License File + run: | + set -x + echo "" >> $GITHUB_STEP_SUMMARY + echo "### License File Validation" >> $GITHUB_STEP_SUMMARY + + if [ ! -f "LICENSE" ]; then + echo "❌ LICENSE file not found" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### ❌ Validation Failed: LICENSE File Missing" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Error:** LICENSE file is required for all MokoStandards-compliant repositories" >> $GITHUB_STEP_SUMMARY + echo "**Action Required:** Add LICENSE file with appropriate open-source license (GPL-3.0-or-later recommended)" >> $GITHUB_STEP_SUMMARY + echo "" + echo "❌ ERROR: LICENSE file not found - This is a critical requirement" + exit 1 + fi + + # Check license type + if grep -qi "GNU GENERAL PUBLIC LICENSE" LICENSE; then + VERSION=$(grep -i "Version 3" LICENSE || echo "") + if [ -n "$VERSION" ]; then + echo "✅ GPL-3.0-or-later license detected" >> $GITHUB_STEP_SUMMARY + else + echo "⚠️ GPL license detected but version unclear" >> $GITHUB_STEP_SUMMARY + fi + elif grep -qi "MIT License" LICENSE; then + echo "✅ MIT license detected" >> $GITHUB_STEP_SUMMARY + elif grep -qi "Apache License" LICENSE; then + echo "✅ Apache license detected" >> $GITHUB_STEP_SUMMARY + else + echo "ℹ️ License type could not be automatically detected" >> $GITHUB_STEP_SUMMARY + fi + + repository-structure: + name: Repository Structure Validation + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Check Required Directories + run: | + set -x + echo "## 📁 Repository Structure Validation" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + MISSING=0 + PRESENT=0 + TOTAL=2 + + echo "### Required Directories" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "| Directory | Status | Files | Size | Notes |" >> $GITHUB_STEP_SUMMARY + echo "|-----------|--------|-------|------|-------|" >> $GITHUB_STEP_SUMMARY + + # Check required directories + for dir in docs .github; do + if [ -d "$dir" ]; then + FILE_COUNT=$(find "$dir" -type f 2>/dev/null | wc -l) + DIR_SIZE=$(du -sh "$dir" 2>/dev/null | cut -f1) + echo "| $dir/ | ✅ Pass | $FILE_COUNT files | $DIR_SIZE | Complete |" >> $GITHUB_STEP_SUMMARY + PRESENT=$((PRESENT + 1)) + else + echo "| $dir/ | ❌ **Missing** | - | - | **Action Required** |" >> $GITHUB_STEP_SUMMARY + MISSING=$((MISSING + 1)) + fi + done + + echo "" >> $GITHUB_STEP_SUMMARY + PERCENT=$((PRESENT * 100 / TOTAL)) + echo "**Compliance Score:** $PERCENT% ($PRESENT/$TOTAL directories present)" >> $GITHUB_STEP_SUMMARY + + if [ "$MISSING" -gt 0 ]; then + echo "" >> $GITHUB_STEP_SUMMARY + echo "### 🔴 Critical Issues: $MISSING" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Remediation Steps:**" >> $GITHUB_STEP_SUMMARY + [ ! -d "docs" ] && echo "- Create docs directory: \`mkdir docs && echo '# Documentation' > docs/README.md\`" >> $GITHUB_STEP_SUMMARY + [ ! -d ".github" ] && echo "- Create .github directory: \`mkdir -p .github/workflows\`" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "📚 Reference: [MokoStandards Repository Structure](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/core-structure.md)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### ❌ Validation Failed: Required Directories Missing" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Status:** Repository structure does not meet MokoStandards requirements" >> $GITHUB_STEP_SUMMARY + echo "**Missing:** $MISSING required director(y|ies)" >> $GITHUB_STEP_SUMMARY + echo "**Compliance:** $PERCENT% ($PRESENT/$TOTAL directories present)" >> $GITHUB_STEP_SUMMARY + echo "" + echo "❌ ERROR: Required directories missing - See job summary for remediation steps" + exit 1 + fi + + - name: Check Required Files + run: | + set -x + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Required Files" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + MISSING=0 + PRESENT=0 + TOTAL=5 + + echo "| File | Status | Size | Last Modified | Notes |" >> $GITHUB_STEP_SUMMARY + echo "|------|--------|------|---------------|-------|" >> $GITHUB_STEP_SUMMARY + + # Check required files (CHANGELOG handled separately via find -iname to support src/ChangeLog.md) + for file in README.md LICENSE CONTRIBUTING.md SECURITY.md .editorconfig; do + if [ -f "$file" ]; then + FILE_SIZE=$(wc -c < "$file" 2>/dev/null | awk '{printf "%.1f KB", $1/1024}') + LAST_MOD=$(stat -c %y "$file" 2>/dev/null | cut -d' ' -f1 || echo "Unknown") + CONTENT_CHECK="" + + # Basic content validation + case "$file" in + "README.md") + LINES=$(wc -l < "$file") + [ "$LINES" -lt 10 ] && CONTENT_CHECK="⚠️ Too short" + ;; + "LICENSE") + [ $(wc -c < "$file") -lt 100 ] && CONTENT_CHECK="⚠️ Incomplete?" + ;; + esac + + echo "| $file | ✅ Pass | $FILE_SIZE | $LAST_MOD | Complete $CONTENT_CHECK |" >> $GITHUB_STEP_SUMMARY + PRESENT=$((PRESENT + 1)) + else + echo "| $file | ❌ **Missing** | - | - | **Required** |" >> $GITHUB_STEP_SUMMARY + MISSING=$((MISSING + 1)) + fi + done + + echo "" >> $GITHUB_STEP_SUMMARY + PERCENT=$((PRESENT * 100 / TOTAL)) + echo "**Compliance Score:** $PERCENT% ($PRESENT/$TOTAL files present)" >> $GITHUB_STEP_SUMMARY + + if [ "$MISSING" -gt 0 ]; then + echo "" >> $GITHUB_STEP_SUMMARY + echo "### 🔴 Critical Issues: $MISSING" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Remediation Steps:**" >> $GITHUB_STEP_SUMMARY + [ ! -f "README.md" ] && echo "- Create README.md: Use [template](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/templates/docs/required/README.md)" >> $GITHUB_STEP_SUMMARY + [ ! -f "LICENSE" ] && echo "- Add LICENSE file: Choose from [OSI-approved licenses](https://opensource.org/licenses)" >> $GITHUB_STEP_SUMMARY + [ ! -f "CONTRIBUTING.md" ] && echo "- Create CONTRIBUTING.md: Use [template](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/templates/docs/required/CONTRIBUTING.md)" >> $GITHUB_STEP_SUMMARY + [ ! -f "SECURITY.md" ] && echo "- Create SECURITY.md: Use [template](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/templates/docs/required/SECURITY.md)" >> $GITHUB_STEP_SUMMARY + [ ! -f ".editorconfig" ] && echo "- Add .editorconfig: Use [template](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/templates/.editorconfig)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "📚 Reference: [MokoStandards File Requirements](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/file-header-standards.md)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### ❌ Validation Failed: Required Files Missing" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Status:** Repository files do not meet MokoStandards requirements" >> $GITHUB_STEP_SUMMARY + echo "**Missing:** $MISSING required file(s)" >> $GITHUB_STEP_SUMMARY + echo "**Compliance:** $PERCENT% ($PRESENT/$TOTAL files present)" >> $GITHUB_STEP_SUMMARY + echo "" + echo "❌ ERROR: Required files missing - See job summary for remediation steps" + exit 1 + fi + + coding-standards: + name: Coding Standards Check + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Check for Tab Characters + run: | + set -x + echo "### Tab Character Detection" >> $GITHUB_STEP_SUMMARY + + # Policy: Tabs are DEFAULT. Only check for tabs in files that REQUIRE spaces. + # Languages requiring spaces: YAML, Python, Haskell, F#, CoffeeScript, Nim, JSON, RST + TABS_IN_SPACES_FILES=$(find . -type f \ + \( -name "*.yml" -o -name "*.yaml" \ + -o -name "*.py" \ + -o -name "*.hs" -o -name "*.lhs" \ + -o -name "*.fs" -o -name "*.fsx" -o -name "*.fsi" \ + -o -name "*.coffee" -o -name "*.litcoffee" \ + -o -name "*.nim" -o -name "*.nims" -o -name "*.nimble" \ + -o -name "*.json" \ + -o -name "*.rst" \) \ + ! -path "./vendor/*" \ + ! -path "./node_modules/*" \ + ! -path "./.git/*" \ + -exec grep -l $'\t' {} \; 2>/dev/null | head -10) + + if [ -n "$TABS_IN_SPACES_FILES" ]; then + echo "⚠️ Tab characters found in files that require spaces:" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "$TABS_IN_SPACES_FILES" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "These languages require spaces (tabs will break): YAML, Python, Haskell, F#, CoffeeScript, Nim, JSON, RST" >> $GITHUB_STEP_SUMMARY + echo "All other files (including .md, .ps1, LICENSE, etc.) may use tabs per MokoStandards policy" >> $GITHUB_STEP_SUMMARY + else + echo "✅ No tabs found in files requiring spaces" >> $GITHUB_STEP_SUMMARY + echo "Note: Tabs are allowed in most files (policy default). Only checked files requiring spaces." >> $GITHUB_STEP_SUMMARY + fi + + - name: Check File Encoding + run: | + set -x + echo "" >> $GITHUB_STEP_SUMMARY + echo "### File Encoding Check" >> $GITHUB_STEP_SUMMARY + + # Check for UTF-8 encoding (ASCII is a subset of UTF-8 and is acceptable) + NON_UTF8=$(find . -type f \( -name "*.php" -o -name "*.js" -o -name "*.md" \) \ + ! -path "./vendor/*" \ + ! -path "./node_modules/*" \ + ! -path "./.git/*" \ + -exec file {} \; | grep -v "UTF-8" | grep -v "ASCII" | head -5 || true) + + if [ -n "$NON_UTF8" ]; then + echo "⚠️ Non-UTF-8 files detected:" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "$NON_UTF8" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + else + echo "✅ All source files appear to be UTF-8 encoded" >> $GITHUB_STEP_SUMMARY + fi + + - name: Check Line Endings + run: | + set -x + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Line Ending Check" >> $GITHUB_STEP_SUMMARY + + # Check for CRLF line endings + CRLF_FILES=$(find . -type f \( -name "*.php" -o -name "*.js" -o -name "*.md" \) \ + ! -path "./vendor/*" \ + ! -path "./node_modules/*" \ + ! -path "./.git/*" \ + -exec file {} \; | grep "CRLF" | head -5 || true) + + if [ -n "$CRLF_FILES" ]; then + echo "⚠️ Files with CRLF line endings found:" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "$CRLF_FILES" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "MokoStandards requires LF line endings" >> $GITHUB_STEP_SUMMARY + else + echo "✅ Line endings are consistent (LF)" >> $GITHUB_STEP_SUMMARY + fi + + version-consistency: + name: Version Consistency Check + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Set up PHP + uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2.31.0 + with: + php-version: '8.1' + extensions: json + tools: composer + coverage: none + + - name: Setup MokoStandards tools + env: + GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }} + COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}' + run: | + git clone --depth 1 --branch version/04 --quiet \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + /tmp/mokostandards 2>/dev/null || true + if [ -d "/tmp/mokostandards" ] && [ -f "/tmp/mokostandards/composer.json" ]; then + cd /tmp/mokostandards + composer install --no-dev --no-interaction --quiet 2>/dev/null || true + fi + + - name: Run Version Consistency Check + id: version_check + run: | + set -x + echo "## 🔢 Version Consistency Validation" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Use MokoStandards tools (no Composer needed on the governed repo) + if [ -f "/tmp/mokostandards/api/validate/check_version_consistency.php" ]; then + php /tmp/mokostandards/api/validate/check_version_consistency.php --path . --verbose 2>&1 | tee /tmp/version-check.log + EXIT_CODE=${PIPESTATUS[0]} + elif [ -f "api/validate/check_version_consistency.php" ]; then + php api/validate/check_version_consistency.php --path . --verbose 2>&1 | tee /tmp/version-check.log + EXIT_CODE=${PIPESTATUS[0]} + else + echo "⏭️ MokoStandards tools not available — skipping version check" >> $GITHUB_STEP_SUMMARY + exit 0 + fi + + echo '```' >> $GITHUB_STEP_SUMMARY + cat /tmp/version-check.log >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + + if [ "$EXIT_CODE" -eq 0 ]; then + echo "✅ All version numbers are consistent" >> $GITHUB_STEP_SUMMARY + else + echo "❌ Version drift detected" >> $GITHUB_STEP_SUMMARY + exit 1 + fi + + + # ════════════════════════════════════════════════════════════════════════ + # TIER 2 — IMPORTANT (should pass) + # ════════════════════════════════════════════════════════════════════════ + workflow-validation: + name: Workflow Configuration Check + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Check Required Workflows + run: | + set -x + echo "### GitHub Actions Workflows" >> $GITHUB_STEP_SUMMARY + + WORKFLOWS_DIR=".github/workflows" + + if [ ! -d "$WORKFLOWS_DIR" ]; then + echo "❌ No workflows directory found" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### ❌ Validation Failed: Workflows Directory Missing" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Error:** .github/workflows directory is required for CI/CD automation" >> $GITHUB_STEP_SUMMARY + echo "**Action Required:** Create .github/workflows directory and add GitHub Actions workflows" >> $GITHUB_STEP_SUMMARY + echo "" + echo "❌ ERROR: .github/workflows directory not found" + exit 1 + fi + + # Check for recommended workflows + CI_FOUND=false + for wf in ci.yml build.yml ci-dolibarr.yml ci-joomla.yml; do + if [ -f "$WORKFLOWS_DIR/$wf" ]; then + echo "✅ CI workflow present ($wf)" >> $GITHUB_STEP_SUMMARY + CI_FOUND=true + break + fi + done + if [ "$CI_FOUND" = "false" ]; then + echo "⚠️ No CI workflow found (ci.yml, build.yml, ci-dolibarr.yml, or ci-joomla.yml)" >> $GITHUB_STEP_SUMMARY + fi + + if [ -f "$WORKFLOWS_DIR/codeql-analysis.yml" ]; then + echo "✅ CodeQL security scanning present" >> $GITHUB_STEP_SUMMARY + else + echo "⚠️ CodeQL workflow not found" >> $GITHUB_STEP_SUMMARY + fi + + # Check for MokoStandards-synced workflows + for wf in deploy-dev.yml deploy-demo.yml deploy-rs.yml sync-version-on-merge.yml auto-release.yml standards-compliance.yml enterprise-firewall-setup.yml; do + if [ -f "$WORKFLOWS_DIR/$wf" ]; then + echo "✅ ${wf}" >> $GITHUB_STEP_SUMMARY + else + echo "⚠️ ${wf} not found (synced from MokoStandards)" >> $GITHUB_STEP_SUMMARY + fi + done + + - name: Validate Workflow Syntax + run: | + set -x + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Workflow YAML Syntax" >> $GITHUB_STEP_SUMMARY + + INVALID=0 + for workflow in $(find .github/workflows -maxdepth 1 -type f \( -name "*.yml" -o -name "*.yaml" \) 2>/dev/null); do + if [ -f "$workflow" ]; then + if python3 -c "import yaml, sys; yaml.safe_load(open(sys.argv[1]))" "$workflow" 2>/dev/null; then + echo "✅ $(basename $workflow)" >> $GITHUB_STEP_SUMMARY + else + echo "❌ $(basename $workflow) - invalid YAML" >> $GITHUB_STEP_SUMMARY + INVALID=$((INVALID + 1)) + fi + fi + done + + if [ "$INVALID" -gt 0 ]; then + echo "" >> $GITHUB_STEP_SUMMARY + echo "### ❌ Validation Failed: Invalid Workflow YAML Syntax" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Error:** $INVALID workflow file(s) have invalid YAML syntax" >> $GITHUB_STEP_SUMMARY + echo "**Action Required:** Fix YAML syntax errors in the marked workflow files" >> $GITHUB_STEP_SUMMARY + echo "**Tool:** Run \`python3 -c \"import yaml; yaml.safe_load(open('.github/workflows/FILE.yml'))\"\` locally" >> $GITHUB_STEP_SUMMARY + echo "" + echo "❌ ERROR: $INVALID workflow file(s) with invalid YAML syntax" + exit 1 + fi + + echo "" >> $GITHUB_STEP_SUMMARY + echo "### ✅ All Workflow Files Have Valid YAML Syntax" >> $GITHUB_STEP_SUMMARY + echo "" + echo "✅ SUCCESS: All workflow files passed YAML validation" + + - name: Validate CodeQL Configuration + if: hashFiles('.github/workflows/codeql-analysis.yml') != '' + run: | + set -e + echo "" >> $GITHUB_STEP_SUMMARY + echo "### CodeQL Language Configuration" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Inline validation (rewritten from Python to bash for PHP-only architecture) + CODEQL_FILE=".github/workflows/codeql-analysis.yml" + + if [ ! -f "$CODEQL_FILE" ]; then + echo "⚠️ CodeQL workflow file not found" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### ⚠️ CodeQL Workflow Not Found" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Status:** CodeQL workflow file not present - skipping language validation" >> $GITHUB_STEP_SUMMARY + echo "" + echo "⚠️ INFO: CodeQL workflow not found - Skipping validation" + exit 0 + fi + + echo "**CodeQL Configuration Analysis**" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Extract configured languages from workflow + LANGUAGES=$(grep -A5 "language:" "$CODEQL_FILE" | grep -oP "(?<=')[^']+(?=')" | tr '\n' ' ' || echo "") + + # Check if this is a configuration-only scan (no languages specified) + if grep -q "category.*language:config" "$CODEQL_FILE"; then + echo "**Scan Type:** Configuration-only (no language matrix)" >> $GITHUB_STEP_SUMMARY + echo "**Status:** ✅ Valid configuration for PHP-only repository" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "This CodeQL workflow scans YAML, JSON, shell scripts for security issues." >> $GITHUB_STEP_SUMMARY + echo "PHP security is handled by SecurityValidator enterprise library." >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "✅ SUCCESS: CodeQL configuration-only scan properly configured" + exit 0 + fi + + if [ -z "$LANGUAGES" ]; then + echo "❌ No languages configured in CodeQL workflow" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### ❌ Validation Failed: CodeQL Languages Not Configured" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Error:** CodeQL workflow exists but has no languages configured" >> $GITHUB_STEP_SUMMARY + echo "**Action Required:** Configure appropriate languages in codeql-analysis.yml" >> $GITHUB_STEP_SUMMARY + echo "" + echo "❌ ERROR: No languages configured in CodeQL workflow" + exit 1 + fi + + echo "**Configured Languages:** $LANGUAGES" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Validate language presence in repository + INVALID_LANGS="" + VALID_LANGS="" + + for LANG in $LANGUAGES; do + case "$LANG" in + python) + # Check for Python files (should be none in v04.00.04) + if find . -name "*.py" -type f ! -path "./.git/*" | grep -q .; then + VALID_LANGS="$VALID_LANGS python" + echo "✅ Python: Found Python files" >> $GITHUB_STEP_SUMMARY + else + INVALID_LANGS="$INVALID_LANGS python" + echo "❌ Python: No Python files found (PHP-only repository)" >> $GITHUB_STEP_SUMMARY + fi + ;; + javascript|typescript) + # Check for JS/TS files + if find . \( -name "*.js" -o -name "*.ts" -o -name "*.json" \) -type f ! -path "./.git/*" ! -path "./node_modules/*" | grep -q .; then + VALID_LANGS="$VALID_LANGS $LANG" + echo "✅ $LANG: Found JavaScript/TypeScript/JSON files" >> $GITHUB_STEP_SUMMARY + else + INVALID_LANGS="$INVALID_LANGS $LANG" + echo "⚠️ $LANG: No JavaScript/TypeScript files found" >> $GITHUB_STEP_SUMMARY + fi + ;; + java) + if find . -name "*.java" -type f ! -path "./.git/*" | grep -q .; then + VALID_LANGS="$VALID_LANGS java" + echo "✅ Java: Found Java files" >> $GITHUB_STEP_SUMMARY + else + INVALID_LANGS="$INVALID_LANGS java" + echo "⚠️ Java: No Java files found" >> $GITHUB_STEP_SUMMARY + fi + ;; + go) + if find . -name "*.go" -type f ! -path "./.git/*" | grep -q .; then + VALID_LANGS="$VALID_LANGS go" + echo "✅ Go: Found Go files" >> $GITHUB_STEP_SUMMARY + else + INVALID_LANGS="$INVALID_LANGS go" + echo "⚠️ Go: No Go files found" >> $GITHUB_STEP_SUMMARY + fi + ;; + cpp|c) + if find . \( -name "*.cpp" -o -name "*.c" -o -name "*.h" \) -type f ! -path "./.git/*" | grep -q .; then + VALID_LANGS="$VALID_LANGS $LANG" + echo "✅ $LANG: Found C/C++ files" >> $GITHUB_STEP_SUMMARY + else + INVALID_LANGS="$INVALID_LANGS $LANG" + echo "⚠️ $LANG: No C/C++ files found" >> $GITHUB_STEP_SUMMARY + fi + ;; + ruby) + if find . -name "*.rb" -type f ! -path "./.git/*" | grep -q .; then + VALID_LANGS="$VALID_LANGS ruby" + echo "✅ Ruby: Found Ruby files" >> $GITHUB_STEP_SUMMARY + else + INVALID_LANGS="$INVALID_LANGS ruby" + echo "⚠️ Ruby: No Ruby files found" >> $GITHUB_STEP_SUMMARY + fi + ;; + *) + echo "⚠️ $LANG: Unknown language, skipping validation" >> $GITHUB_STEP_SUMMARY + ;; + esac + done + + echo "" >> $GITHUB_STEP_SUMMARY + + # Report results + if [ -n "$INVALID_LANGS" ]; then + echo "**⚠️ Warning:** Some configured languages may not have corresponding files:" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "Invalid languages: $INVALID_LANGS" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Note:** This is informational. CodeQL will skip languages without source files." >> $GITHUB_STEP_SUMMARY + echo "For PHP repository (v04.00.04), JavaScript language covers JSON/YAML/shell scripts." >> $GITHUB_STEP_SUMMARY + else + echo "✅ **All configured CodeQL languages have corresponding source files**" >> $GITHUB_STEP_SUMMARY + fi + + # Always succeed - this is informational only + echo "" >> $GITHUB_STEP_SUMMARY + echo "### ✅ CodeQL Configuration Validation Complete" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Status:** CodeQL language configuration reviewed successfully" >> $GITHUB_STEP_SUMMARY + echo "" + echo "✅ SUCCESS: CodeQL validation complete" + exit 0 + + documentation-quality: + name: Documentation Quality Check + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Validate README.md + run: | + set -x + echo "## 📚 Documentation Quality Check" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### README.md Analysis" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ ! -f "README.md" ]; then + echo "❌ **Critical:** README.md not found" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### ❌ Validation Failed: README.md Missing" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Error:** README.md is required for all MokoStandards-compliant repositories" >> $GITHUB_STEP_SUMMARY + echo "**Action Required:** Create README.md with project description, setup instructions, and usage examples" >> $GITHUB_STEP_SUMMARY + echo "" + echo "❌ ERROR: README.md not found - This is a critical requirement" + exit 1 + fi + + # Detailed content analysis + SIZE=$(wc -c < README.md) + LINES=$(wc -l < README.md) + WORDS=$(wc -w < README.md) + HEADINGS=$(grep -c "^#" README.md || echo 0) + LINKS=$(grep -c "\[.*\](.*)" README.md || echo 0) + CODE_BLOCKS=$(grep -c '```' README.md || echo 0) + + echo "| Metric | Value | Status | Recommendation |" >> $GITHUB_STEP_SUMMARY + echo "|--------|-------|--------|----------------|" >> $GITHUB_STEP_SUMMARY + + # Size check + SIZE_STATUS="✅ Good" + SIZE_REC="Adequate length" + if [ "$SIZE" -lt 500 ]; then + SIZE_STATUS="⚠️ Warning" + SIZE_REC="Add more content (min 500 bytes)" + elif [ "$SIZE" -gt 50000 ]; then + SIZE_STATUS="⚠️ Warning" + SIZE_REC="Consider splitting into multiple docs" + fi + echo "| Size | $SIZE bytes | $SIZE_STATUS | $SIZE_REC |" >> $GITHUB_STEP_SUMMARY + + # Line count + LINES_STATUS="✅ Good" + LINES_REC="Good size" + if [ "$LINES" -lt 20 ]; then + LINES_STATUS="⚠️ Warning" + LINES_REC="Add more sections (min 20 lines)" + fi + echo "| Lines | $LINES | $LINES_STATUS | $LINES_REC |" >> $GITHUB_STEP_SUMMARY + + # Word count + WORDS_STATUS="✅ Good" + WORDS_REC="Good detail" + if [ "$WORDS" -lt 100 ]; then + WORDS_STATUS="⚠️ Warning" + WORDS_REC="Add more description (min 100 words)" + fi + echo "| Words | $WORDS | $WORDS_STATUS | $WORDS_REC |" >> $GITHUB_STEP_SUMMARY + + # Headings + HEADINGS_STATUS="✅ Good" + HEADINGS_REC="Well structured" + if [ "$HEADINGS" -lt 3 ]; then + HEADINGS_STATUS="⚠️ Warning" + HEADINGS_REC="Add more sections (min 3 headings)" + fi + echo "| Headings | $HEADINGS | $HEADINGS_STATUS | $HEADINGS_REC |" >> $GITHUB_STEP_SUMMARY + + # Links + LINKS_STATUS="✅ Good" + LINKS_REC="Includes references" + if [ "$LINKS" -lt 1 ]; then + LINKS_STATUS="ℹ️ Info" + LINKS_REC="Consider adding useful links" + fi + echo "| Links | $LINKS | $LINKS_STATUS | $LINKS_REC |" >> $GITHUB_STEP_SUMMARY + + # Code blocks + CODE_STATUS="✅ Good" + CODE_REC="Includes examples" + if [ "$CODE_BLOCKS" -eq 0 ]; then + CODE_STATUS="ℹ️ Info" + CODE_REC="Consider adding code examples" + fi + echo "| Code blocks | $CODE_BLOCKS | $CODE_STATUS | $CODE_REC |" >> $GITHUB_STEP_SUMMARY + + echo "" >> $GITHUB_STEP_SUMMARY + + # Check for key sections + echo "**Section Coverage:**" >> $GITHUB_STEP_SUMMARY + MISSING_COUNT=0 + grep -qi "install\|setup\|getting started" README.md && echo "- ✅ Installation/Setup instructions" >> $GITHUB_STEP_SUMMARY || { echo "- ⚠️ Missing: Installation/Setup" >> $GITHUB_STEP_SUMMARY; MISSING_COUNT=$((MISSING_COUNT + 1)); } + grep -qi "usage\|example\|how to" README.md && echo "- ✅ Usage examples" >> $GITHUB_STEP_SUMMARY || { echo "- ⚠️ Missing: Usage examples" >> $GITHUB_STEP_SUMMARY; MISSING_COUNT=$((MISSING_COUNT + 1)); } + grep -qi "license" README.md && echo "- ✅ License information" >> $GITHUB_STEP_SUMMARY || { echo "- ⚠️ Missing: License information" >> $GITHUB_STEP_SUMMARY; MISSING_COUNT=$((MISSING_COUNT + 1)); } + grep -qi "contribut" README.md && echo "- ✅ Contributing guidelines" >> $GITHUB_STEP_SUMMARY || echo "- ℹ️ Optional: Contributing section" >> $GITHUB_STEP_SUMMARY + + if [ "$MISSING_COUNT" -gt 0 ]; then + echo "" >> $GITHUB_STEP_SUMMARY + echo "**⚠️ $MISSING_COUNT important sections missing**" >> $GITHUB_STEP_SUMMARY + fi + + - name: Validate CHANGELOG.md + run: | + set -x + echo "" >> $GITHUB_STEP_SUMMARY + echo "### CHANGELOG.md Analysis" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Locate changelog case-insensitively; accepted at root, src/, or docs/ + CHANGELOG_PATH=$(find . -maxdepth 3 \( -path ./.git -o -path ./node_modules \) -prune \ + -o -iname "changelog.md" -print | head -1 | sed 's|^\./||') + + if [ -z "$CHANGELOG_PATH" ]; then + echo "❌ **Critical:** CHANGELOG.md not found (checked root, src/, docs/)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### ❌ Validation Failed: CHANGELOG.md Missing" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Error:** CHANGELOG.md is required for all MokoStandards-compliant repositories" >> $GITHUB_STEP_SUMMARY + echo "**Action Required:** Create CHANGELOG.md following [Keep a Changelog](https://keepachangelog.com/) format" >> $GITHUB_STEP_SUMMARY + echo "" + echo "❌ ERROR: CHANGELOG.md not found - This is a critical requirement" + exit 1 + fi + + echo "📄 Found: $CHANGELOG_PATH" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Analyze changelog structure + VERSIONS=$(grep -c "## \[" "$CHANGELOG_PATH" || echo 0) + UNRELEASED=$(grep -c "## \[Unreleased\]" "$CHANGELOG_PATH" || echo 0) + DATES=$(grep -c "[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}" "$CHANGELOG_PATH" || echo 0) + SIZE=$(wc -c < "$CHANGELOG_PATH") + + echo "| Metric | Value | Status | Notes |" >> $GITHUB_STEP_SUMMARY + echo "|--------|-------|--------|-------|" >> $GITHUB_STEP_SUMMARY + + # Check format + if grep -qi "## \[.*\]" "$CHANGELOG_PATH"; then + echo "| Format | Keep a Changelog | ✅ Pass | Standard format |" >> $GITHUB_STEP_SUMMARY + else + echo "| Format | Custom | ⚠️ Warning | Consider [Keep a Changelog](https://keepachangelog.com/) |" >> $GITHUB_STEP_SUMMARY + fi + + # Version count + VERSIONS_STATUS="✅ Good" + VERSIONS_NOTE="Well maintained" + if [ "$VERSIONS" -lt 1 ]; then + VERSIONS_STATUS="⚠️ Warning" + VERSIONS_NOTE="Add version entries" + fi + echo "| Versions | $VERSIONS | $VERSIONS_STATUS | $VERSIONS_NOTE |" >> $GITHUB_STEP_SUMMARY + + # Unreleased section + if [ "$UNRELEASED" -gt 0 ]; then + echo "| Unreleased | Yes | ✅ Good | Active development tracked |" >> $GITHUB_STEP_SUMMARY + else + echo "| Unreleased | No | ℹ️ Info | Consider adding [Unreleased] section |" >> $GITHUB_STEP_SUMMARY + fi + + # Dates + DATES_STATUS="✅ Good" + if [ "$DATES" -lt 1 ]; then + DATES_STATUS="⚠️ Warning" + DATES_NOTE="Add release dates" + else + DATES_NOTE="Dates present" + fi + echo "| Release dates | $DATES | $DATES_STATUS | $DATES_NOTE |" >> $GITHUB_STEP_SUMMARY + + # Check for standard sections + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Changelog Sections:**" >> $GITHUB_STEP_SUMMARY + grep -qi "### Added" "$CHANGELOG_PATH" && echo "- ✅ Added section" >> $GITHUB_STEP_SUMMARY || echo "- ℹ️ Added section (optional)" >> $GITHUB_STEP_SUMMARY + grep -qi "### Changed" "$CHANGELOG_PATH" && echo "- ✅ Changed section" >> $GITHUB_STEP_SUMMARY || echo "- ℹ️ Changed section (optional)" >> $GITHUB_STEP_SUMMARY + grep -qi "### Fixed" "$CHANGELOG_PATH" && echo "- ✅ Fixed section" >> $GITHUB_STEP_SUMMARY || echo "- ℹ️ Fixed section (optional)" >> $GITHUB_STEP_SUMMARY + + echo "" >> $GITHUB_STEP_SUMMARY + echo "📚 Reference: [Keep a Changelog](https://keepachangelog.com/)" >> $GITHUB_STEP_SUMMARY + + - name: Check Documentation Index + run: | + set -x + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Documentation Index" >> $GITHUB_STEP_SUMMARY + + if [ -f "docs/index.md" ] || [ -f "docs/README.md" ]; then + echo "✅ Documentation index found" >> $GITHUB_STEP_SUMMARY + else + echo "⚠️ No documentation index (docs/index.md or docs/README.md)" >> $GITHUB_STEP_SUMMARY + fi + + readme-completeness: + name: README Completeness Check + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Check README Sections + run: | + set -x + echo "## 📄 README Completeness Check" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ ! -f "README.md" ]; then + echo "❌ README.md not found" >> $GITHUB_STEP_SUMMARY + exit 1 + fi + + # Required sections + REQUIRED_SECTIONS=("Installation" "Usage" "Contributing" "License") + MISSING=0 + PRESENT=0 + + echo "### Required Sections" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + for section in "${REQUIRED_SECTIONS[@]}"; do + if grep -qi "##.*$section" README.md; then + echo "✅ $section" >> $GITHUB_STEP_SUMMARY + PRESENT=$((PRESENT + 1)) + else + echo "❌ $section" >> $GITHUB_STEP_SUMMARY + MISSING=$((MISSING + 1)) + fi + done + + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Completeness**: $PRESENT/${#REQUIRED_SECTIONS[@]} required sections present" >> $GITHUB_STEP_SUMMARY + + if [ "$MISSING" -gt 0 ]; then + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Action Required**: Add missing sections to README.md" >> $GITHUB_STEP_SUMMARY + exit 1 + fi + + # ============================================================================ + # PHASE 3: Future Enhancements + # ============================================================================ + + git-hygiene: + name: Git Repository Hygiene + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + fetch-depth: 0 + + - name: Check .gitignore + run: | + set -x + echo "### .gitignore Validation" >> $GITHUB_STEP_SUMMARY + + if [ ! -f ".gitignore" ]; then + echo "⚠️ .gitignore file not found" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### ⚠️ Warning: .gitignore Not Found" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Status:** .gitignore file is recommended but not required" >> $GITHUB_STEP_SUMMARY + echo "**Recommendation:** Add .gitignore to exclude build artifacts, dependencies, and temporary files" >> $GITHUB_STEP_SUMMARY + echo "" + echo "⚠️ WARNING: .gitignore file not found - Continuing validation" + exit 0 + fi + + # Check for common exclusions + MISSING="" + grep -q "vendor/" .gitignore || MISSING="${MISSING}vendor/ " + grep -q "node_modules/" .gitignore || MISSING="${MISSING}node_modules/ " + + if [ -n "$MISSING" ]; then + echo "⚠️ .gitignore may be missing common exclusions: $MISSING" >> $GITHUB_STEP_SUMMARY + else + echo "✅ .gitignore appears complete" >> $GITHUB_STEP_SUMMARY + fi + + - name: Check for Large Files + run: | + set -x + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Large File Detection" >> $GITHUB_STEP_SUMMARY + + # Find files larger than 1MB + LARGE_FILES=$(find . -type f -size +1M ! -path "./.git/*" ! -path "./vendor/*" ! -path "./node_modules/*" | head -5) + + if [ -n "$LARGE_FILES" ]; then + echo "⚠️ Large files detected (>1MB):" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "$LARGE_FILES" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "Consider using Git LFS for large binary files" >> $GITHUB_STEP_SUMMARY + else + echo "✅ No unusually large files detected" >> $GITHUB_STEP_SUMMARY + fi + + script-integrity: + name: Script Integrity Validation + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Set up Python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: '3.x' + + - name: Validate Script Integrity + id: script_check + run: | + set -x + echo "## 🔐 Script Integrity Validation" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ -f "api/.script-registry.json" ]; then + echo "### Critical Scripts" >> $GITHUB_STEP_SUMMARY + php api/maintenance/update_sha_hashes.php \ + --dry-run --verbose | tee /tmp/script-validation.log + + EXIT_CODE=$? + + echo "" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + cat /tmp/script-validation.log >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + + if [ "$EXIT_CODE" -eq 0 ]; then + echo "" >> $GITHUB_STEP_SUMMARY + echo "✅ All critical scripts validated successfully!" >> $GITHUB_STEP_SUMMARY + exit 0 + else + echo "" >> $GITHUB_STEP_SUMMARY + echo "❌ Script integrity violations detected" >> $GITHUB_STEP_SUMMARY + echo "**Action Required:** Review validation report and update registry" >> $GITHUB_STEP_SUMMARY + exit 1 + fi + else + echo "ℹ️ Script registry not found - skipping integrity check" >> $GITHUB_STEP_SUMMARY + exit 0 + fi + + + # ════════════════════════════════════════════════════════════════════════ + # TIER 3 — QUALITY (code quality metrics) + # ════════════════════════════════════════════════════════════════════════ + line-length-validation: + name: Line Length Check + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Check Line Lengths + run: | + set -x + echo "## 📏 Line Length Validation" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Line length standards: + # - General source code: 120 characters (hard limit) + # - YAML workflows: 180 characters (exception for GitHub Actions) + # - Markdown files: No limit (content-focused) + + echo "### Line Length Standards" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "| File Type | Soft Limit | Hard Limit |" >> $GITHUB_STEP_SUMMARY + echo "|-----------|------------|------------|" >> $GITHUB_STEP_SUMMARY + echo "| General source code | 80 chars | 120 chars |" >> $GITHUB_STEP_SUMMARY + echo "| YAML workflows | 80 chars | 180 chars |" >> $GITHUB_STEP_SUMMARY + echo "| Markdown files | N/A | No limit |" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Check YAML files (using yamllint which is already configured) + echo "### YAML Files (180 char limit)" >> $GITHUB_STEP_SUMMARY + + YAML_VIOLATIONS=0 + if command -v yamllint >/dev/null 2>&1; then + # Install yamllint if not present + : + else + pip install yamllint >/dev/null 2>&1 || true + fi + + # Run yamllint and count line-length warnings + YAML_OUTPUT=$(yamllint .github/workflows/*.yml 2>&1 | grep "line too long" || true) + if [ -n "$YAML_OUTPUT" ]; then + YAML_VIOLATIONS=$(echo "$YAML_OUTPUT" | wc -l) + echo "⚠️ Found $YAML_VIOLATIONS lines exceeding 180 characters in YAML files" >> $GITHUB_STEP_SUMMARY + echo "
View warnings (informational only)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "$YAML_OUTPUT" | head -20 >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY + else + echo "✅ All YAML files comply with 180 character limit" >> $GITHUB_STEP_SUMMARY + fi + echo "" >> $GITHUB_STEP_SUMMARY + + # Check source code files (PHP, Python, JavaScript, etc.) for 120 char limit + echo "### Source Code Files (120 char limit)" >> $GITHUB_STEP_SUMMARY + + LONG_LINES=$(find . -type f \ + \( -name "*.php" -o -name "*.py" -o -name "*.js" -o -name "*.ts" \ + -o -name "*.go" -o -name "*.rs" -o -name "*.java" -o -name "*.c" \ + -o -name "*.cpp" -o -name "*.h" -o -name "*.sh" \) \ + ! -path "./vendor/*" \ + ! -path "./node_modules/*" \ + ! -path "./.git/*" \ + ! -path "./build/*" \ + ! -path "./dist/*" \ + -exec awk 'length > 120 { print FILENAME ":" NR ": " length " chars" }' {} \; 2>/dev/null | head -20 || true) + + if [ -n "$LONG_LINES" ]; then + LINE_COUNT=$(echo "$LONG_LINES" | wc -l) + echo "⚠️ Found $LINE_COUNT source code lines exceeding 120 characters" >> $GITHUB_STEP_SUMMARY + echo "
View violations (informational)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "$LONG_LINES" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY + else + echo "✅ All source code files comply with 120 character limit" >> $GITHUB_STEP_SUMMARY + fi + echo "" >> $GITHUB_STEP_SUMMARY + + # Confirm Markdown files are not checked + echo "### Markdown Files" >> $GITHUB_STEP_SUMMARY + echo "✅ Markdown files have no line length limit per coding standards" >> $GITHUB_STEP_SUMMARY + echo "Rationale: Content-focused format, URLs, tables, and natural prose flow" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Summary + echo "### Summary" >> $GITHUB_STEP_SUMMARY + echo "This check is **informational only** and does not block merges." >> $GITHUB_STEP_SUMMARY + echo "Line length standards help maintain code readability." >> $GITHUB_STEP_SUMMARY + echo "Exceptions documented in: \`docs/policy/coding-style-guide.md\`" >> $GITHUB_STEP_SUMMARY + + file-naming-standards: + name: File Naming Standards + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Check File Naming + run: | + set -x + echo "## 📝 File Naming Standards" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + VIOLATIONS=0 + + # Check PHP files (should be PascalCase for classes) + INVALID_PHP=$(find . -name "*.php" ! -path "./vendor/*" ! -path "./.git/*" ! -regex ".*/[A-Z][a-zA-Z0-9]*\.php" ! -name "index.php" ! -name "functions.php" | wc -l || echo 0) + + # Check config files (should be kebab-case) + INVALID_CONFIG=$(find . -name "*.yml" -o -name "*.yaml" -o -name "*.json" ! -path "./vendor/*" ! -path "./.git/*" ! -path "./node_modules/*" | grep -E "[A-Z_]" | wc -l || echo 0) + + echo "### Naming Violations" >> $GITHUB_STEP_SUMMARY + echo "- **PHP files not PascalCase**: $INVALID_PHP" >> $GITHUB_STEP_SUMMARY + echo "- **Config files not kebab-case**: $INVALID_CONFIG" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + VIOLATIONS=$((INVALID_PHP + INVALID_CONFIG)) + + if [ "$VIOLATIONS" -gt 0 ]; then + echo "⚠️ Found $VIOLATIONS naming convention violation(s)" >> $GITHUB_STEP_SUMMARY + echo "**Recommendation**: Follow naming conventions for consistency" >> $GITHUB_STEP_SUMMARY + else + echo "✅ File naming conventions followed" >> $GITHUB_STEP_SUMMARY + fi + + insecure-patterns: + name: Insecure Code Pattern Detection + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Scan for Insecure Patterns + run: | + set -x + echo "## 🔒 Insecure Code Pattern Detection" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + VIOLATIONS=0 + + # PHP: SQL injection patterns + if grep -r -n "\\$_\(GET\|POST\|REQUEST\).*mysql_query\|mysqli_query" . --include="*.php" ! -path "./vendor/*" 2>/dev/null > /tmp/sql_inject.txt; then + COUNT=$(wc -l < /tmp/sql_inject.txt) + echo "⚠️ Found $COUNT potential SQL injection pattern(s)" >> $GITHUB_STEP_SUMMARY + VIOLATIONS=$((VIOLATIONS + COUNT)) + fi + + # PHP: eval/exec usage + if grep -r -n "eval\|exec\|system\|passthru\|shell_exec" . --include="*.php" ! -path "./vendor/*" 2>/dev/null > /tmp/exec.txt; then + COUNT=$(wc -l < /tmp/exec.txt) + echo "⚠️ Found $COUNT dangerous function call(s)" >> $GITHUB_STEP_SUMMARY + VIOLATIONS=$((VIOLATIONS + COUNT)) + fi + + # Python: eval usage + if grep -r -n "eval(" . --include="*.py" 2>/dev/null > /tmp/py_eval.txt; then + COUNT=$(wc -l < /tmp/py_eval.txt) + echo "⚠️ Found $COUNT Python eval() usage(s)" >> $GITHUB_STEP_SUMMARY + VIOLATIONS=$((VIOLATIONS + COUNT)) + fi + + echo "" >> $GITHUB_STEP_SUMMARY + + if [ "$VIOLATIONS" -gt 0 ]; then + echo "**Total Violations**: $VIOLATIONS" >> $GITHUB_STEP_SUMMARY + echo "**Recommendation**: Review and secure flagged patterns" >> $GITHUB_STEP_SUMMARY + else + echo "✅ No insecure patterns detected" >> $GITHUB_STEP_SUMMARY + fi + + code-complexity: + name: Code Complexity Analysis + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Setup PHP + uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2.31.0 + with: + php-version: '8.1' + + - name: Analyze Complexity + run: | + set -x + echo "## 📊 Code Complexity Analysis" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + PHP_COUNT=$(find . -name "*.php" ! -path "./vendor/*" ! -path "./.git/*" | wc -l) + + if [ "$PHP_COUNT" -gt 0 ]; then + # Install phploc + wget https://phar.phpunit.de/phploc.phar 2>/dev/null + chmod +x phploc.phar + + echo "### PHP Code Metrics" >> $GITHUB_STEP_SUMMARY + if ./phploc.phar --exclude vendor --exclude .git . 2>&1 | tee /tmp/phploc.txt; then + COMPLEXITY=$(grep "Cyclomatic Complexity" /tmp/phploc.txt | grep "Average" | awk '{print $NF}' || echo "N/A") + echo "**Average Cyclomatic Complexity**: $COMPLEXITY" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ "$COMPLEXITY" != "N/A" ] && [ $(echo "$COMPLEXITY > 10" | bc -l) -eq 1 ]; then + echo "⚠️ Average complexity exceeds recommended threshold (10)" >> $GITHUB_STEP_SUMMARY + echo "**Recommendation**: Refactor complex functions" >> $GITHUB_STEP_SUMMARY + else + echo "✅ Code complexity within acceptable limits" >> $GITHUB_STEP_SUMMARY + fi + fi + else + echo "ℹ️ No PHP files found for complexity analysis" >> $GITHUB_STEP_SUMMARY + fi + + code-duplication: + name: Code Duplication Detection + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Setup PHP + uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2.31.0 + with: + php-version: '8.1' + + - name: Detect Duplicates + run: | + set -x + echo "## 🔁 Code Duplication Detection" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Check if PHP files exist + PHP_COUNT=$(find . -name "*.php" ! -path "./vendor/*" ! -path "./.git/*" | wc -l) + + if [ "$PHP_COUNT" -gt 0 ]; then + echo "### PHP Code Duplication" >> $GITHUB_STEP_SUMMARY + + # Install phpcpd + wget https://phar.phpunit.de/phpcpd.phar 2>/dev/null + chmod +x phpcpd.phar + + # Run duplication detection + if ./phpcpd.phar --exclude vendor --exclude .git . 2>&1 | tee /tmp/phpcpd.txt; then + DUPLICATION=$(grep "Found" /tmp/phpcpd.txt | grep -oE "[0-9]+\.[0-9]+%" | head -1 || echo "0.00%") + echo "📊 **Duplication Rate**: $DUPLICATION" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + DUPLICATION_NUM=$(echo "$DUPLICATION" | sed 's/%//') + if [ $(echo "$DUPLICATION_NUM > 5.0" | bc -l) -eq 1 ]; then + echo "⚠️ Code duplication exceeds 5% threshold" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY + echo "View duplication details" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + cat /tmp/phpcpd.txt >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY + else + echo "✅ Code duplication within acceptable limits (<5%)" >> $GITHUB_STEP_SUMMARY + fi + else + echo "✅ No significant code duplication detected" >> $GITHUB_STEP_SUMMARY + fi + else + echo "ℹ️ No PHP files found for duplication analysis" >> $GITHUB_STEP_SUMMARY + fi + + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Note**: This is an informational check to encourage DRY principles." >> $GITHUB_STEP_SUMMARY + + dead-code-detection: + name: Dead Code Detection + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Setup Python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: '3.x' + + - name: Detect Dead Code + run: | + set -x + echo "## 🗑️ Dead Code Detection" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + PY_COUNT=$(find . -name "*.py" ! -path "./vendor/*" ! -path "./.git/*" ! -path "./venv/*" | wc -l) + + if [ "$PY_COUNT" -gt 0 ]; then + pip install vulture 2>/dev/null + echo "### Python Dead Code" >> $GITHUB_STEP_SUMMARY + + if vulture . --exclude vendor,venv,.git 2>&1 | tee /tmp/vulture.txt; then + DEAD_COUNT=$(wc -l < /tmp/vulture.txt || echo 0) + if [ "$DEAD_COUNT" -gt 0 ]; then + echo "⚠️ Found $DEAD_COUNT potential dead code item(s)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY + echo "View dead code" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + head -50 /tmp/vulture.txt >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY + else + echo "✅ No dead code detected" >> $GITHUB_STEP_SUMMARY + fi + fi + else + echo "ℹ️ No Python files found for dead code analysis" >> $GITHUB_STEP_SUMMARY + fi + + + # ════════════════════════════════════════════════════════════════════════ + # TIER 4 — SUPPLEMENTARY (informational) + # ════════════════════════════════════════════════════════════════════════ + file-size-limits: + name: File Size Limits + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Check File Sizes + run: | + set -x + echo "## 📦 File Size Validation" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Exempt file types (allowed to be large) + EXEMPT="! -name *.mmdb ! -name *.woff2 ! -name *.woff ! -name *.ttf ! -name *.otf" + + # Find large files (>15MB warning, >20MB critical) + LARGE_FILES=$(find . -type f -size +15M $EXEMPT ! -path "./.git/*" ! -path "./vendor/*" ! -path "./node_modules/*" 2>/dev/null | wc -l) + HUGE_FILES=$(find . -type f -size +20M $EXEMPT ! -path "./.git/*" ! -path "./vendor/*" ! -path "./node_modules/*" 2>/dev/null | wc -l) + + echo "### Size Thresholds" >> $GITHUB_STEP_SUMMARY + echo "- **Warning**: Files >15MB" >> $GITHUB_STEP_SUMMARY + echo "- **Critical**: Files >20MB" >> $GITHUB_STEP_SUMMARY + echo "- **Exempt**: .mmdb, .woff2, .woff, .ttf, .otf" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ "$HUGE_FILES" -gt 0 ]; then + echo "❌ **Critical**: Found $HUGE_FILES file(s) exceeding 20MB" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY + echo "View files >20MB" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + find . -type f -size +20M $EXEMPT ! -path "./.git/*" ! -path "./vendor/*" ! -path "./node_modules/*" -exec ls -lh {} + 2>/dev/null | awk '{print $5, $9}' >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Action Required**: Remove or optimize files >20MB" >> $GITHUB_STEP_SUMMARY + exit 1 + elif [ "$LARGE_FILES" -gt 0 ]; then + echo "⚠️ **Warning**: Found $LARGE_FILES file(s) between 15MB and 20MB" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY + echo "View files >15MB" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + find . -type f -size +15M $EXEMPT ! -path "./.git/*" ! -path "./vendor/*" ! -path "./node_modules/*" -exec ls -lh {} + 2>/dev/null | awk '{print $5, $9}' >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Recommendation**: Consider optimizing large files" >> $GITHUB_STEP_SUMMARY + else + echo "✅ All files within acceptable size limits" >> $GITHUB_STEP_SUMMARY + fi + + binary-file-detection: + name: Binary File Detection + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Detect Binary Files + run: | + set -x + echo "## 🔍 Binary File Detection" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Find binary files excluding allowed types + BINARIES=$(find . -type f ! -path "./.git/*" ! -path "./vendor/*" ! -path "./node_modules/*" \ + ! -name "*.png" ! -name "*.jpg" ! -name "*.jpeg" ! -name "*.gif" ! -name "*.svg" ! -name "*.ico" \ + ! -name "*.woff" ! -name "*.woff2" ! -name "*.ttf" ! -name "*.eot" \ + -exec file {} \; | grep -v "text" | grep -v "empty" | wc -l || echo 0) + + if [ "$BINARIES" -gt 0 ]; then + echo "⚠️ Found $BINARIES non-image binary file(s)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY + echo "View binary files" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + find . -type f ! -path "./.git/*" ! -path "./vendor/*" ! -path "./node_modules/*" \ + ! -name "*.png" ! -name "*.jpg" ! -name "*.jpeg" ! -name "*.gif" ! -name "*.svg" ! -name "*.ico" \ + ! -name "*.woff" ! -name "*.woff2" ! -name "*.ttf" ! -name "*.eot" \ + -exec file {} \; | grep -v "text" | grep -v "empty" | cut -d: -f1 >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Recommendation**: Source control should primarily contain text files" >> $GITHUB_STEP_SUMMARY + else + echo "✅ No unexpected binary files detected" >> $GITHUB_STEP_SUMMARY + fi + + # ============================================================================ + # PHASE 4: Nice to Have Checks + # ============================================================================ + + todo-fixme-tracking: + name: TODO/FIXME Tracking + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Track Technical Debt + run: | + set -x + echo "## 📝 TODO/FIXME Tracking" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "Tracking technical debt markers in source code." >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Search for technical debt markers + PATTERNS="TODO|FIXME|HACK|XXX" + EXTENSIONS="*.php *.py *.js *.ts *.go *.rs *.java *.c *.cpp *.h *.hpp *.sh" + + echo "### Technical Debt Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + TOTAL_COUNT=0 + for ext in $EXTENSIONS; do + COUNT=$(find . -type f -name "$ext" ! -path "./.git/*" ! -path "./vendor/*" ! -path "./node_modules/*" -exec grep -n -E "($PATTERNS)" {} + 2>/dev/null | wc -l || echo 0) + TOTAL_COUNT=$((TOTAL_COUNT + COUNT)) + done + + if [ "$TOTAL_COUNT" -gt 0 ]; then + echo "⚠️ Found **$TOTAL_COUNT** technical debt item(s)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY + echo "View technical debt items" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + for ext in $EXTENSIONS; do + find . -type f -name "$ext" ! -path "./.git/*" ! -path "./vendor/*" ! -path "./node_modules/*" -exec grep -n -H -E "($PATTERNS)" {} + 2>/dev/null | head -100 || true + done >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY + else + echo "✅ No technical debt markers found" >> $GITHUB_STEP_SUMMARY + fi + + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Note**: This is an informational check. Technical debt items don't block compliance." >> $GITHUB_STEP_SUMMARY + + dependency-vulnerabilities: + name: Dependency Vulnerability Scanning + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Setup PHP + uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2.31.0 + with: + php-version: '8.1' + + - name: Setup Python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: '3.x' + + - name: Scan Dependencies + run: | + set -x + echo "## 🛡️ Dependency Vulnerability Scanning" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + VULNERABILITIES=0 + + # PHP Dependencies + if [ -f "composer.json" ]; then + echo "### PHP Dependencies (composer)" >> $GITHUB_STEP_SUMMARY + if composer audit --no-dev 2>&1 | tee /tmp/php_audit.txt; then + echo "✅ No PHP vulnerabilities detected" >> $GITHUB_STEP_SUMMARY + else + VULN_COUNT=$(grep -c "vulnerability" /tmp/php_audit.txt || echo 0) + echo "⚠️ Found $VULN_COUNT PHP vulnerability/vulnerabilities" >> $GITHUB_STEP_SUMMARY + VULNERABILITIES=$((VULNERABILITIES + VULN_COUNT)) + fi + echo "" >> $GITHUB_STEP_SUMMARY + fi + + # Python Dependencies + if [ -f "requirements.txt" ]; then + echo "### Python Dependencies" >> $GITHUB_STEP_SUMMARY + pip install pip-audit 2>&1 > /dev/null + if pip-audit -r requirements.txt 2>&1 | tee /tmp/py_audit.txt; then + echo "✅ No Python vulnerabilities detected" >> $GITHUB_STEP_SUMMARY + else + VULN_COUNT=$(grep -c "vulnerability" /tmp/py_audit.txt || echo 0) + echo "⚠️ Found $VULN_COUNT Python vulnerability/vulnerabilities" >> $GITHUB_STEP_SUMMARY + VULNERABILITIES=$((VULNERABILITIES + VULN_COUNT)) + fi + echo "" >> $GITHUB_STEP_SUMMARY + fi + + # NPM Dependencies + if [ -f "package.json" ]; then + echo "### NPM Dependencies" >> $GITHUB_STEP_SUMMARY + if npm audit --production 2>&1 | tee /tmp/npm_audit.txt; then + echo "✅ No NPM vulnerabilities detected" >> $GITHUB_STEP_SUMMARY + else + VULN_COUNT=$(grep -c "vulnerability" /tmp/npm_audit.txt || echo 0) + echo "⚠️ Found $VULN_COUNT NPM vulnerability/vulnerabilities" >> $GITHUB_STEP_SUMMARY + VULNERABILITIES=$((VULNERABILITIES + VULN_COUNT)) + fi + echo "" >> $GITHUB_STEP_SUMMARY + fi + + if [ "$VULNERABILITIES" -gt 0 ]; then + echo "**Total Vulnerabilities**: $VULNERABILITIES" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Action Required**: Update vulnerable dependencies" >> $GITHUB_STEP_SUMMARY + exit 1 + else + echo "✅ No dependency vulnerabilities detected" >> $GITHUB_STEP_SUMMARY + fi + + unused-dependencies: + name: Unused Dependencies Check + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Setup PHP + uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2.31.0 + with: + php-version: '8.1' + + - name: Check Unused Dependencies + run: | + set -x + echo "## 📦 Unused Dependencies Check" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ -f "composer.json" ]; then + echo "### PHP Dependencies" >> $GITHUB_STEP_SUMMARY + + # Install composer-unused + composer global require icanhazstring/composer-unused 2>/dev/null || true + + if composer global exec composer-unused 2>&1 | tee /tmp/unused.txt; then + UNUSED_COUNT=$(grep "unused" /tmp/unused.txt | wc -l || echo 0) + if [ "$UNUSED_COUNT" -gt 0 ]; then + echo "⚠️ Found $UNUSED_COUNT unused dependency/dependencies" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY + echo "View unused dependencies" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + cat /tmp/unused.txt >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY + else + echo "✅ No unused dependencies detected" >> $GITHUB_STEP_SUMMARY + fi + else + echo "✅ All dependencies appear to be in use" >> $GITHUB_STEP_SUMMARY + fi + else + echo "ℹ️ No composer.json found" >> $GITHUB_STEP_SUMMARY + fi + + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Recommendation**: Remove unused dependencies to reduce attack surface" >> $GITHUB_STEP_SUMMARY + + broken-link-detection: + name: Broken Link Detection + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Check Internal Links + run: | + set -x + echo "## 🔗 Broken Link Detection" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "Checking internal links in markdown files." >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + BROKEN_LINKS=0 + CHECKED_LINKS=0 + + # Find all markdown files + MD_FILES=$(find . -name "*.md" ! -path "./.git/*" ! -path "./vendor/*" ! -path "./node_modules/*") + + for file in $MD_FILES; do + # Extract markdown links [text](path) + while IFS= read -r line; do + # Extract path from [text](path) + link=$(echo "$line" | sed -n 's/.*\](\([^)]*\)).*/\1/p') + + # Skip external links (http/https) + if echo "$link" | grep -qE "^https?://"; then + continue + fi + + # Skip anchors only + if echo "$link" | grep -qE "^#"; then + continue + fi + + CHECKED_LINKS=$((CHECKED_LINKS + 1)) + + # Get directory of the markdown file + basedir=$(dirname "$file") + + # Resolve relative path + if [ -n "$link" ]; then + # Remove anchor if present + clean_link=$(echo "$link" | sed 's/#.*//') + + # Check if file exists + if [ ! -e "$basedir/$clean_link" ] && [ ! -e "$clean_link" ]; then + echo "Broken link in $file: $link" >> /tmp/broken_links.txt + BROKEN_LINKS=$((BROKEN_LINKS + 1)) + fi + fi + done < <(grep -o '\[.*\](.*)' "$file" 2>/dev/null || true) + done + + echo "### Link Validation Results" >> $GITHUB_STEP_SUMMARY + echo "- **Links Checked**: $CHECKED_LINKS" >> $GITHUB_STEP_SUMMARY + echo "- **Broken Links**: $BROKEN_LINKS" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ "$BROKEN_LINKS" -gt 0 ]; then + echo "⚠️ Found $BROKEN_LINKS broken internal link(s)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY + echo "View broken links" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + cat /tmp/broken_links.txt 2>/dev/null >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Recommendation**: Fix or remove broken links to maintain documentation quality" >> $GITHUB_STEP_SUMMARY + else + if [ "$CHECKED_LINKS" -gt 0 ]; then + echo "✅ All internal links are valid" >> $GITHUB_STEP_SUMMARY + else + echo "ℹ️ No internal links found to check" >> $GITHUB_STEP_SUMMARY + fi + fi + + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Note**: This check validates internal file references only. External URLs are not validated." >> $GITHUB_STEP_SUMMARY + + # ============================================================================ + # PHASE 2: Medium Priority Checks + # ============================================================================ + + api-documentation: + name: API Documentation Coverage + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Check Documentation + run: | + set -x + echo "## 📚 API Documentation Coverage" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Count public functions/classes + PUBLIC_METHODS=$(grep -r "public function" . --include="*.php" ! -path "./vendor/*" | wc -l || echo 0) + DOCUMENTED=$(grep -B5 -r "public function" . --include="*.php" ! -path "./vendor/*" | grep -c "/\*\*" || echo 0) + + if [ "$PUBLIC_METHODS" -gt 0 ]; then + COVERAGE=$((DOCUMENTED * 100 / PUBLIC_METHODS)) + echo "**Documentation Coverage**: $COVERAGE% ($DOCUMENTED/$PUBLIC_METHODS)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ "$COVERAGE" -lt 80 ]; then + echo "⚠️ Documentation coverage below 80% threshold" >> $GITHUB_STEP_SUMMARY + echo "**Recommendation**: Add PHPDoc blocks to public methods" >> $GITHUB_STEP_SUMMARY + else + echo "✅ Good documentation coverage" >> $GITHUB_STEP_SUMMARY + fi + else + echo "ℹ️ No public methods found for documentation check" >> $GITHUB_STEP_SUMMARY + fi + + accessibility-check: + name: Accessibility Check + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Check Accessibility + run: | + set -x + echo "## ♿ Accessibility Check" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + HTML_COUNT=$(find . -name "*.html" ! -path "./vendor/*" ! -path "./.git/*" ! -path "./node_modules/*" | wc -l || echo 0) + MD_IMG_COUNT=$(find . -name "*.md" ! -path "./vendor/*" ! -path "./.git/*" -exec grep -l "!\[" {} + 2>/dev/null | wc -l || echo 0) + + if [ "$HTML_COUNT" -gt 0 ] || [ "$MD_IMG_COUNT" -gt 0 ]; then + # Check for images without alt text + MISSING_ALT=0 + + if [ "$HTML_COUNT" -gt 0 ]; then + MISSING_ALT=$(grep -r "> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ "$MISSING_ALT" -gt 0 ]; then + echo "⚠️ Found images without alt text" >> $GITHUB_STEP_SUMMARY + echo "**Recommendation**: Add descriptive alt text for accessibility" >> $GITHUB_STEP_SUMMARY + else + echo "✅ All images have alt text" >> $GITHUB_STEP_SUMMARY + fi + else + echo "ℹ️ No HTML files found for accessibility check" >> $GITHUB_STEP_SUMMARY + fi + + performance-metrics: + name: Performance Metrics + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Check Performance Metrics + run: | + set -x + echo "## ⚡ Performance Metrics" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Check if JavaScript bundles exist + if [ -f "package.json" ]; then + echo "### Bundle Analysis" >> $GITHUB_STEP_SUMMARY + + # Check for common bundle files + BUNDLE_SIZE=0 + if [ -d "dist" ]; then + BUNDLE_SIZE=$(du -sb dist/ 2>/dev/null | cut -f1 || echo 0) + elif [ -d "build" ]; then + BUNDLE_SIZE=$(du -sb build/ 2>/dev/null | cut -f1 || echo 0) + fi + + if [ "$BUNDLE_SIZE" -gt 0 ]; then + BUNDLE_MB=$((BUNDLE_SIZE / 1024 / 1024)) + echo "**Bundle Size**: ${BUNDLE_MB}MB" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ "$BUNDLE_MB" -gt 5 ]; then + echo "⚠️ Bundle size exceeds 5MB threshold" >> $GITHUB_STEP_SUMMARY + echo "**Recommendation**: Optimize bundle size" >> $GITHUB_STEP_SUMMARY + else + echo "✅ Bundle size within acceptable limits" >> $GITHUB_STEP_SUMMARY + fi + else + echo "ℹ️ No build artifacts found" >> $GITHUB_STEP_SUMMARY + fi + else + echo "ℹ️ Not a JavaScript project" >> $GITHUB_STEP_SUMMARY + fi + + enterprise-readiness: + name: Enterprise Readiness Check + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Set up PHP + uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2.31.0 + with: + php-version: '8.1' + extensions: json, mbstring + tools: composer + coverage: none + + - name: Install API Package + env: + GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }} + COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}' + run: | + if [ -f "composer.json" ]; then + composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader + else + echo "No composer.json — pulling MokoStandards tools" + if [ ! -d "/tmp/mokostandards" ]; then + git clone --depth 1 --branch version/04 --quiet \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + /tmp/mokostandards 2>/dev/null || true + if [ -f "/tmp/mokostandards/composer.json" ]; then + cd /tmp/mokostandards && composer install --no-dev --no-interaction --quiet 2>/dev/null || true + cd - + fi + fi + fi + + - name: Check Enterprise Readiness + id: enterprise_check + run: | + echo "" >> $GITHUB_STEP_SUMMARY + + SCRIPT="" + if [ -f "api/validate/check_enterprise_readiness.php" ]; then + SCRIPT="api/validate/check_enterprise_readiness.php" + elif [ -f "/tmp/mokostandards/api/validate/check_enterprise_readiness.php" ]; then + SCRIPT="/tmp/mokostandards/api/validate/check_enterprise_readiness.php" + fi + + if [ -n "$SCRIPT" ]; then + php "$SCRIPT" --verbose | tee /tmp/enterprise-check.log + EXIT_CODE=$? + + echo "" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + cat /tmp/enterprise-check.log >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + + if [ "$EXIT_CODE" -eq 0 ]; then + echo "" >> $GITHUB_STEP_SUMMARY + echo "✅ Repository meets enterprise readiness criteria!" >> $GITHUB_STEP_SUMMARY + exit 0 + else + echo "" >> $GITHUB_STEP_SUMMARY + echo "⚠️ Enterprise readiness issues detected" >> $GITHUB_STEP_SUMMARY + echo "**Note:** This is informational - review recommendations to improve" >> $GITHUB_STEP_SUMMARY + exit 0 # Non-blocking + fi + else + echo "ℹ️ Enterprise readiness check script not found - skipping" >> $GITHUB_STEP_SUMMARY + exit 0 + fi + + repository-health: + name: Repository Health Check + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Set up PHP + uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2.31.0 + with: + php-version: '8.1' + extensions: json, mbstring + tools: composer + coverage: none + + - name: Install API Package + env: + GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }} + COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}' + run: | + if [ -f "composer.json" ]; then + composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader + else + echo "No composer.json — pulling MokoStandards tools" + if [ ! -d "/tmp/mokostandards" ]; then + git clone --depth 1 --branch version/04 --quiet \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + /tmp/mokostandards 2>/dev/null || true + if [ -f "/tmp/mokostandards/composer.json" ]; then + cd /tmp/mokostandards && composer install --no-dev --no-interaction --quiet 2>/dev/null || true + cd - + fi + fi + fi + + - name: Check Repository Health + id: health_check + run: | + echo "" >> $GITHUB_STEP_SUMMARY + + SCRIPT="" + if [ -f "api/validate/check_repo_health.php" ]; then + SCRIPT="api/validate/check_repo_health.php" + elif [ -f "/tmp/mokostandards/api/validate/check_repo_health.php" ]; then + SCRIPT="/tmp/mokostandards/api/validate/check_repo_health.php" + fi + + if [ -n "$SCRIPT" ]; then + php "$SCRIPT" --verbose | tee /tmp/health-check.log + EXIT_CODE=$? + + echo "" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + cat /tmp/health-check.log >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + + if [ "$EXIT_CODE" -eq 0 ]; then + echo "" >> $GITHUB_STEP_SUMMARY + echo "✅ Repository health check passed!" >> $GITHUB_STEP_SUMMARY + exit 0 + else + echo "" >> $GITHUB_STEP_SUMMARY + echo "⚠️ Repository health issues detected" >> $GITHUB_STEP_SUMMARY + echo "**Note:** This is informational - review recommendations to improve" >> $GITHUB_STEP_SUMMARY + exit 0 # Non-blocking + fi + else + echo "ℹ️ Repository health check script not found - skipping" >> $GITHUB_STEP_SUMMARY + exit 0 + fi + + terraform-validation: + name: Terraform Configuration Validation + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Setup Terraform + uses: hashicorp/setup-terraform@5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85 # v4.0.0 + with: + terraform_version: "1.0" + + - name: Validate Terraform Files + run: | + set -x + echo "## 🏗️ Terraform Configuration Validation" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Check if terraform files exist + TF_COUNT=$(find . -name "*.tf" -type f | wc -l || echo 0) + + if [ "$TF_COUNT" -eq 0 ]; then + echo "ℹ️ No Terraform files found in repository" >> $GITHUB_STEP_SUMMARY + exit 0 + fi + + echo "**Terraform Files Found**: $TF_COUNT" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Validation Results + VALIDATION_PASSED=true + WARNINGS=0 + ERRORS=0 + + # 1. Check .github/config.tf location (not root override files) + echo "### Override Configuration Check" >> $GITHUB_STEP_SUMMARY + LEGACY_OVERRIDES=$(find . -maxdepth 1 -name "*override*.tf" -o -name "MokoStandards.override.tf" 2>/dev/null | wc -l || echo 0) + if [ "$LEGACY_OVERRIDES" -gt 0 ]; then + echo "⚠️ Found legacy override files in root directory" >> $GITHUB_STEP_SUMMARY + echo "**Expected Location**: .github/config.tf" >> $GITHUB_STEP_SUMMARY + echo "**Legacy files found**: $LEGACY_OVERRIDES" >> $GITHUB_STEP_SUMMARY + WARNINGS=$((WARNINGS + 1)) + else + if [ -f ".github/config.tf" ]; then + echo "✅ Override configuration in correct location (.github/config.tf)" >> $GITHUB_STEP_SUMMARY + else + echo "ℹ️ No override configuration found" >> $GITHUB_STEP_SUMMARY + fi + fi + echo "" >> $GITHUB_STEP_SUMMARY + + # 2. Terraform Syntax Validation + echo "### Terraform Syntax Validation" >> $GITHUB_STEP_SUMMARY + SYNTAX_ERRORS=0 + + # Find all directories with terraform files + for dir in $(find . -name "*.tf" -type f -exec dirname {} \; | sort -u); do + cd "$dir" || continue + echo "Validating: $dir" >> $GITHUB_STEP_SUMMARY + + # Initialize without backend + terraform init -backend=false > /dev/null 2>&1 || true + + # Validate + if terraform validate -no-color > /tmp/tf_validate.txt 2>&1; then + echo " ✅ Syntax valid" >> $GITHUB_STEP_SUMMARY + else + echo " ❌ Syntax errors found" >> $GITHUB_STEP_SUMMARY + cat /tmp/tf_validate.txt >> $GITHUB_STEP_SUMMARY + SYNTAX_ERRORS=$((SYNTAX_ERRORS + 1)) + VALIDATION_PASSED=false + fi + cd - > /dev/null + done + echo "" >> $GITHUB_STEP_SUMMARY + + if [ "$SYNTAX_ERRORS" -eq 0 ]; then + echo "✅ All Terraform files have valid syntax" >> $GITHUB_STEP_SUMMARY + else + echo "❌ Found $SYNTAX_ERRORS directories with syntax errors" >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + SYNTAX_ERRORS)) + fi + echo "" >> $GITHUB_STEP_SUMMARY + + # 3. Terraform Formatting Check + echo "### Terraform Formatting Check" >> $GITHUB_STEP_SUMMARY + FORMAT_ISSUES=0 + + for tf_file in $(find . -name "*.tf" -type f); do + if ! terraform fmt -check=true -no-color "$tf_file" > /dev/null 2>&1; then + FORMAT_ISSUES=$((FORMAT_ISSUES + 1)) + fi + done + + if [ "$FORMAT_ISSUES" -eq 0 ]; then + echo "✅ All Terraform files properly formatted" >> $GITHUB_STEP_SUMMARY + else + echo "⚠️ Found $FORMAT_ISSUES files with formatting issues" >> $GITHUB_STEP_SUMMARY + echo "**Fix**: Run \`terraform fmt -recursive\`" >> $GITHUB_STEP_SUMMARY + WARNINGS=$((WARNINGS + 1)) + fi + echo "" >> $GITHUB_STEP_SUMMARY + + # 4. Check for file_metadata blocks + echo "### File Metadata Validation" >> $GITHUB_STEP_SUMMARY + MISSING_METADATA=0 + + for tf_file in $(find . -name "*.tf" -type f); do + if ! grep -q "file_metadata" "$tf_file"; then + MISSING_METADATA=$((MISSING_METADATA + 1)) + fi + done + + if [ "$MISSING_METADATA" -eq 0 ]; then + echo "✅ All Terraform files contain file_metadata block" >> $GITHUB_STEP_SUMMARY + else + echo "⚠️ Found $MISSING_METADATA files missing file_metadata block" >> $GITHUB_STEP_SUMMARY + echo "**Reference**: docs/policy/terraform-file-standards.md" >> $GITHUB_STEP_SUMMARY + WARNINGS=$((WARNINGS + 1)) + fi + echo "" >> $GITHUB_STEP_SUMMARY + + # 5. Version Consistency Check + echo "### Version Consistency Check" >> $GITHUB_STEP_SUMMARY + VERSION_MISMATCHES=0 + EXPECTED_VERSION="04.00.04" + + for tf_file in $(find . -name "*.tf" -type f); do + if grep -q "version.*=" "$tf_file"; then + if ! grep -q "version.*=.*\"$EXPECTED_VERSION\"" "$tf_file"; then + VERSION_MISMATCHES=$((VERSION_MISMATCHES + 1)) + fi + fi + done + + if [ "$VERSION_MISMATCHES" -eq 0 ]; then + echo "✅ All Terraform file versions match $EXPECTED_VERSION" >> $GITHUB_STEP_SUMMARY + else + echo "⚠️ Found $VERSION_MISMATCHES files with version mismatches" >> $GITHUB_STEP_SUMMARY + echo "**Expected Version**: $EXPECTED_VERSION" >> $GITHUB_STEP_SUMMARY + WARNINGS=$((WARNINGS + 1)) + fi + echo "" >> $GITHUB_STEP_SUMMARY + + # 6. Copyright Header Check + echo "### Copyright Header Check" >> $GITHUB_STEP_SUMMARY + MISSING_COPYRIGHT=0 + + for tf_file in $(find . -name "*.tf" -type f); do + if ! grep -q "Copyright (C)" "$tf_file"; then + MISSING_COPYRIGHT=$((MISSING_COPYRIGHT + 1)) + fi + done + + if [ "$MISSING_COPYRIGHT" -eq 0 ]; then + echo "✅ All Terraform files have copyright headers" >> $GITHUB_STEP_SUMMARY + else + echo "⚠️ Found $MISSING_COPYRIGHT files missing copyright headers" >> $GITHUB_STEP_SUMMARY + echo "**Reference**: docs/policy/terraform-file-standards.md" >> $GITHUB_STEP_SUMMARY + WARNINGS=$((WARNINGS + 1)) + fi + echo "" >> $GITHUB_STEP_SUMMARY + + # Summary + echo "---" >> $GITHUB_STEP_SUMMARY + echo "### Validation Summary" >> $GITHUB_STEP_SUMMARY + echo "**Total Files**: $TF_COUNT" >> $GITHUB_STEP_SUMMARY + echo "**Errors**: $ERRORS" >> $GITHUB_STEP_SUMMARY + echo "**Warnings**: $WARNINGS" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ "$VALIDATION_PASSED" = true ] && [ "$ERRORS" -eq 0 ]; then + echo "✅ **Terraform Validation: PASSED**" >> $GITHUB_STEP_SUMMARY + exit 0 + elif [ "$ERRORS" -gt 0 ]; then + echo "❌ **Terraform Validation: FAILED**" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Note**: This is an informational check and does not block merges" >> $GITHUB_STEP_SUMMARY + exit 0 # Informational only + else + echo "⚠️ **Terraform Validation: PASSED WITH WARNINGS**" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Note**: This is an informational check and does not block merges" >> $GITHUB_STEP_SUMMARY + exit 0 # Informational only + fi + + summary: + name: Compliance Summary + runs-on: ubuntu-latest + needs: [ + repository-structure, documentation-quality, coding-standards, line-length-validation, license-compliance, git-hygiene, workflow-validation, version-consistency, script-integrity, enterprise-readiness, repository-health, + todo-fixme-tracking, file-size-limits, secret-scanning, broken-link-detection, + dependency-vulnerabilities, code-duplication, unused-dependencies, readme-completeness, + code-complexity, api-documentation, insecure-patterns, binary-file-detection, + dead-code-detection, file-naming-standards, accessibility-check, performance-metrics, terraform-validation + ] + if: always() + + steps: + - name: Generate Compliance Report + run: | + set -x + echo "# 📊 MokoStandards Compliance Report" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Calculate overall status + REPO_STATUS="${{ needs.repository-structure.result }}" + DOCS_STATUS="${{ needs.documentation-quality.result }}" + CODE_STATUS="${{ needs.coding-standards.result }}" + LINE_LENGTH_STATUS="${{ needs.line-length-validation.result }}" + LICENSE_STATUS="${{ needs.license-compliance.result }}" + GIT_STATUS="${{ needs.git-hygiene.result }}" + WORKFLOW_STATUS="${{ needs.workflow-validation.result }}" + VERSION_STATUS="${{ needs.version-consistency.result }}" + SCRIPT_STATUS="${{ needs.script-integrity.result }}" + ENTERPRISE_STATUS="${{ needs.enterprise-readiness.result }}" + HEALTH_STATUS="${{ needs.repository-health.result }}" + TERRAFORM_STATUS="${{ needs.terraform-validation.result }}" + + PASSED=0 + FAILED=0 + WARNINGS=0 + TOTAL=28 + + # Critical checks (must pass) + [ "$REPO_STATUS" = "success" ] && PASSED=$((PASSED + 1)) || FAILED=$((FAILED + 1)) + [ "$DOCS_STATUS" = "success" ] && PASSED=$((PASSED + 1)) || FAILED=$((FAILED + 1)) + [ "$CODE_STATUS" = "success" ] && PASSED=$((PASSED + 1)) || FAILED=$((FAILED + 1)) + [ "$LICENSE_STATUS" = "success" ] && PASSED=$((PASSED + 1)) || FAILED=$((FAILED + 1)) + [ "$GIT_STATUS" = "success" ] && PASSED=$((PASSED + 1)) || FAILED=$((FAILED + 1)) + [ "$WORKFLOW_STATUS" = "success" ] && PASSED=$((PASSED + 1)) || FAILED=$((FAILED + 1)) + [ "$VERSION_STATUS" = "success" ] && PASSED=$((PASSED + 1)) || FAILED=$((FAILED + 1)) + [ "$SCRIPT_STATUS" = "success" ] && PASSED=$((PASSED + 1)) || FAILED=$((FAILED + 1)) + + # Informational checks (don't fail build) + if [ "$ENTERPRISE_STATUS" = "success" ]; then + PASSED=$((PASSED + 1)) + else + WARNINGS=$((WARNINGS + 1)) + fi + + if [ "$HEALTH_STATUS" = "success" ]; then + PASSED=$((PASSED + 1)) + else + WARNINGS=$((WARNINGS + 1)) + fi + + if [ "$TERRAFORM_STATUS" = "success" ]; then + PASSED=$((PASSED + 1)) + else + WARNINGS=$((WARNINGS + 1)) + fi + + # Adjust total to only count critical checks for compliance percentage + CRITICAL_TOTAL=8 + CRITICAL_PASSED=$((PASSED - WARNINGS)) + COMPLIANCE_PERCENT=$((CRITICAL_PASSED * 100 / CRITICAL_TOTAL)) + + # Overall status badge + if [ "$COMPLIANCE_PERCENT" -eq 100 ]; then + echo "## ✅ Overall Status: **COMPLIANT** ($COMPLIANCE_PERCENT%)" >> $GITHUB_STEP_SUMMARY + elif [ "$COMPLIANCE_PERCENT" -ge 80 ]; then + echo "## ⚠️ Overall Status: **MOSTLY COMPLIANT** ($COMPLIANCE_PERCENT%)" >> $GITHUB_STEP_SUMMARY + elif [ "$COMPLIANCE_PERCENT" -ge 50 ]; then + echo "## ⚠️ Overall Status: **PARTIALLY COMPLIANT** ($COMPLIANCE_PERCENT%)" >> $GITHUB_STEP_SUMMARY + else + echo "## ❌ Overall Status: **NON-COMPLIANT** ($COMPLIANCE_PERCENT%)" >> $GITHUB_STEP_SUMMARY + fi + + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Critical Checks:** $CRITICAL_PASSED/$CRITICAL_TOTAL passed" >> $GITHUB_STEP_SUMMARY + echo "**Total Checks:** $PASSED/$TOTAL passed" >> $GITHUB_STEP_SUMMARY + if [ "$WARNINGS" -gt 0 ]; then + echo "**Informational:** $WARNINGS warning(s)" >> $GITHUB_STEP_SUMMARY + fi + echo "" >> $GITHUB_STEP_SUMMARY + + # Progress bar + FILLED=$((COMPLIANCE_PERCENT / 5)) + EMPTY=$((20 - FILLED)) + BAR="" + for i in $(seq 1 $FILLED); do BAR="${BAR}█"; done + for i in $(seq 1 $EMPTY); do BAR="${BAR}░"; done + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "$BAR $COMPLIANCE_PERCENT%" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Detailed breakdown + echo "## Validation Results" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "| Area | Status | Result | Priority |" >> $GITHUB_STEP_SUMMARY + echo "|------|--------|--------|----------|" >> $GITHUB_STEP_SUMMARY + + # Repository Structure + if [ "$REPO_STATUS" = "success" ]; then + echo "| 📁 Repository Structure | ✅ Pass | Compliant | - |" >> $GITHUB_STEP_SUMMARY + else + echo "| 📁 Repository Structure | ❌ Fail | **Action Required** | 🔴 Critical |" >> $GITHUB_STEP_SUMMARY + fi + + # Documentation Quality + if [ "$DOCS_STATUS" = "success" ]; then + echo "| 📚 Documentation Quality | ✅ Pass | Compliant | - |" >> $GITHUB_STEP_SUMMARY + else + echo "| 📚 Documentation Quality | ❌ Fail | **Action Required** | 🔴 Critical |" >> $GITHUB_STEP_SUMMARY + fi + + # Coding Standards + if [ "$CODE_STATUS" = "success" ]; then + echo "| 💻 Coding Standards | ✅ Pass | Compliant | - |" >> $GITHUB_STEP_SUMMARY + else + echo "| 💻 Coding Standards | ⚠️ Warning | Review Recommended | 🟡 Medium |" >> $GITHUB_STEP_SUMMARY + fi + + # License Compliance + if [ "$LICENSE_STATUS" = "success" ]; then + echo "| ⚖️ License Compliance | ✅ Pass | Compliant | - |" >> $GITHUB_STEP_SUMMARY + else + echo "| ⚖️ License Compliance | ❌ Fail | **Action Required** | 🔴 Critical |" >> $GITHUB_STEP_SUMMARY + fi + + # Git Hygiene + if [ "$GIT_STATUS" = "success" ]; then + echo "| 🧹 Git Repository Hygiene | ✅ Pass | Compliant | - |" >> $GITHUB_STEP_SUMMARY + else + echo "| 🧹 Git Repository Hygiene | ⚠️ Warning | Review Recommended | 🟡 Medium |" >> $GITHUB_STEP_SUMMARY + fi + + # Workflow Configuration + if [ "$WORKFLOW_STATUS" = "success" ]; then + echo "| ⚙️ Workflow Configuration | ✅ Pass | Compliant | - |" >> $GITHUB_STEP_SUMMARY + else + echo "| ⚙️ Workflow Configuration | ⚠️ Warning | Review Recommended | 🟡 Medium |" >> $GITHUB_STEP_SUMMARY + fi + + # Version Consistency + if [ "$VERSION_STATUS" = "success" ]; then + echo "| 🔢 Version Consistency | ✅ Pass | All versions match | - |" >> $GITHUB_STEP_SUMMARY + else + echo "| 🔢 Version Consistency | ❌ Fail | **Action Required** | 🔴 Critical |" >> $GITHUB_STEP_SUMMARY + fi + + # Script Integrity + if [ "$SCRIPT_STATUS" = "success" ]; then + echo "| 🔐 Script Integrity | ✅ Pass | SHA hashes validated | - |" >> $GITHUB_STEP_SUMMARY + else + echo "| 🔐 Script Integrity | ❌ Fail | **Action Required** | 🔴 Critical |" >> $GITHUB_STEP_SUMMARY + fi + + # Enterprise Readiness (Informational) + if [ "$ENTERPRISE_STATUS" = "success" ]; then + echo "| 🏢 Enterprise Readiness | ✅ Pass | Ready for enterprise | ℹ️ Info |" >> $GITHUB_STEP_SUMMARY + else + echo "| 🏢 Enterprise Readiness | ℹ️ Info | Review suggestions | ℹ️ Info |" >> $GITHUB_STEP_SUMMARY + fi + + # Repository Health (Informational) + if [ "$HEALTH_STATUS" = "success" ]; then + echo "| 🏥 Repository Health | ✅ Pass | Health check passed | ℹ️ Info |" >> $GITHUB_STEP_SUMMARY + else + echo "| 🏥 Repository Health | ℹ️ Info | Review recommendations | ℹ️ Info |" >> $GITHUB_STEP_SUMMARY + fi + + echo "" >> $GITHUB_STEP_SUMMARY + + # Action items summary + if [ "$FAILED" -gt 0 ]; then + echo "## ⚡ Action Items" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**$FAILED validation area(s) require attention:**" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + [ "$REPO_STATUS" != "success" ] && echo "- 🔴 **Critical:** Fix repository structure issues" >> $GITHUB_STEP_SUMMARY + [ "$DOCS_STATUS" != "success" ] && echo "- 🔴 **Critical:** Improve documentation quality" >> $GITHUB_STEP_SUMMARY + [ "$LICENSE_STATUS" != "success" ] && echo "- 🔴 **Critical:** Resolve license compliance issues" >> $GITHUB_STEP_SUMMARY + [ "$CODE_STATUS" != "success" ] && echo "- 🟡 **Medium:** Review coding standards violations" >> $GITHUB_STEP_SUMMARY + [ "$GIT_STATUS" != "success" ] && echo "- 🟡 **Medium:** Address git repository hygiene items" >> $GITHUB_STEP_SUMMARY + [ "$WORKFLOW_STATUS" != "success" ] && echo "- 🟡 **Medium:** Review workflow configuration" >> $GITHUB_STEP_SUMMARY + + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Next Steps:**" >> $GITHUB_STEP_SUMMARY + echo "1. Review detailed results in individual job outputs above" >> $GITHUB_STEP_SUMMARY + echo "2. Follow remediation steps provided for each failure" >> $GITHUB_STEP_SUMMARY + echo "3. Re-run this workflow after making corrections" >> $GITHUB_STEP_SUMMARY + echo "4. Reach 100% compliance before merging" >> $GITHUB_STEP_SUMMARY + else + echo "## 🎉 Excellent!" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "Your repository is **fully compliant** with MokoStandards!" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Achievements:**" >> $GITHUB_STEP_SUMMARY + echo "- ✅ All required directories and files present" >> $GITHUB_STEP_SUMMARY + echo "- ✅ Documentation meets quality standards" >> $GITHUB_STEP_SUMMARY + echo "- ✅ Coding standards followed" >> $GITHUB_STEP_SUMMARY + echo "- ✅ License compliance verified" >> $GITHUB_STEP_SUMMARY + echo "- ✅ Git repository well-maintained" >> $GITHUB_STEP_SUMMARY + echo "- ✅ Workflows properly configured" >> $GITHUB_STEP_SUMMARY + fi + + echo "" >> $GITHUB_STEP_SUMMARY + echo "---" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "📚 **Resources:**" >> $GITHUB_STEP_SUMMARY + echo "- [MokoStandards Documentation](https://github.com/mokoconsulting-tech/MokoStandards)" >> $GITHUB_STEP_SUMMARY + echo "- [Repository Structure Guide](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/core-structure.md)" >> $GITHUB_STEP_SUMMARY + echo "- [Documentation Standards](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/document-formatting.md)" >> $GITHUB_STEP_SUMMARY + echo "- [Coding Standards](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/coding-style-guide.md)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "_Generated by MokoStandards Compliance Workflow v${WORKFLOW_VERSION}_" >> $GITHUB_STEP_SUMMARY + + # Create tracking issue for non-compliance if on push + if [ "$COMPLIANCE_PERCENT" -lt 100 ] && [ "${{ github.event_name }}" = "push" ]; then + echo "Creating tracking issue for standards violations..." + fi + + # Exit with error if not fully compliant + if [ "$COMPLIANCE_PERCENT" -lt 100 ]; then + echo "" >> $GITHUB_STEP_SUMMARY + echo "### ❌ Standards Compliance Failed" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Overall Compliance:** $COMPLIANCE_PERCENT%" >> $GITHUB_STEP_SUMMARY + echo "**Status:** Repository does not meet 100% compliance requirement" >> $GITHUB_STEP_SUMMARY + echo "**Action Required:** Review and fix all validation failures above" >> $GITHUB_STEP_SUMMARY + echo "" + echo "❌ ERROR: Standards compliance at $COMPLIANCE_PERCENT% - 100% required" + exit 1 + fi + + echo "" >> $GITHUB_STEP_SUMMARY + echo "### ✅ Full Standards Compliance Achieved" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Overall Compliance:** 100%" >> $GITHUB_STEP_SUMMARY + echo "**Status:** Repository meets all MokoStandards requirements" >> $GITHUB_STEP_SUMMARY + echo "" + echo "✅ SUCCESS: Repository is fully MokoStandards compliant" + + - name: Create or reopen tracking issue for standards violations + if: failure() + env: + GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }} + run: | + REPO="${{ github.repository }}" + RUN_URL="${{ github.server_url }}/${REPO}/actions/runs/${{ github.run_id }}" + DATE=$(date -u '+%Y-%m-%d') + SHA="${{ github.sha }}" + ACTOR="${{ github.actor }}" + BRANCH="${{ github.ref_name }}" + + # Collect failed checks + FAILED="" + [ "${{ needs.repository-structure.result }}" != "success" ] && FAILED="${FAILED}\n- Repository Structure" + [ "${{ needs.documentation-quality.result }}" != "success" ] && FAILED="${FAILED}\n- Documentation Quality" + [ "${{ needs.coding-standards.result }}" != "success" ] && FAILED="${FAILED}\n- Coding Standards" + [ "${{ needs.license-compliance.result }}" != "success" ] && FAILED="${FAILED}\n- License Compliance" + [ "${{ needs.git-hygiene.result }}" != "success" ] && FAILED="${FAILED}\n- Git Hygiene" + [ "${{ needs.workflow-validation.result }}" != "success" ] && FAILED="${FAILED}\n- Workflow Validation" + [ "${{ needs.version-consistency.result }}" != "success" ] && FAILED="${FAILED}\n- Version Consistency" + [ "${{ needs.script-integrity.result }}" != "success" ] && FAILED="${FAILED}\n- Script Integrity" + [ "${{ needs.secret-scanning.result }}" != "success" ] && FAILED="${FAILED}\n- Secret Scanning" + [ "${{ needs.line-length-validation.result }}" != "success" ] && FAILED="${FAILED}\n- Line Length" + [ "${{ needs.file-size-limits.result }}" != "success" ] && FAILED="${FAILED}\n- File Size Limits" + [ "${{ needs.readme-completeness.result }}" != "success" ] && FAILED="${FAILED}\n- README Completeness" + + if [ -z "$FAILED" ]; then + echo "No failed checks to report" + exit 0 + fi + + TITLE="[Standards] Compliance violations — ${DATE}" + BODY="## Standards Compliance Violations + + | Field | Value | + |-------|-------| + | **Branch** | \`${BRANCH}\` | + | **Commit** | \`${SHA:0:7}\` | + | **Actor** | @${ACTOR} | + | **Run** | [View workflow](${RUN_URL}) | + + ### Failed Checks + $(printf '%b' "$FAILED") + + ### Required Actions + 1. Review the [workflow run](${RUN_URL}) for details + 2. Fix each failed check + 3. Push to trigger a new scan + + --- + *Auto-created by standards-compliance workflow*" + + BODY=$(echo "$BODY" | sed 's/^ //') + LABEL="standards-violation" + + gh label create "$LABEL" --repo "$REPO" --color "D73A4A" --description "Standards compliance failure" --force 2>/dev/null || true + + EXISTING=$(gh api "repos/${REPO}/issues?labels=${LABEL}&state=all&per_page=1&sort=created&direction=desc" \ + --jq '.[0].number' 2>/dev/null) + + if [ -n "$EXISTING" ] && [ "$EXISTING" != "null" ]; then + gh api "repos/${REPO}/issues/${EXISTING}" -X PATCH \ + -f title="$TITLE" -f body="$BODY" -f state="open" --silent + echo "Updated issue #${EXISTING}" + else + gh issue create --repo "$REPO" --title "$TITLE" --body "$BODY" \ + --label "$LABEL" --assignee "jmiller" + fi + +# CUSTOMIZATION: +# +# 1. Adjust severity of checks (convert warnings to errors or vice versa) +# 2. Add project-specific validation rules +# 3. Integrate with custom linting tools +# 4. Add notification steps for compliance failures +# 5. Customize required files/directories for your project type + From 6aeb08761374c973cd2e07aec37fe96defddeb94 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 15:46:35 +0000 Subject: [PATCH 04/28] chore: sync auto-bump.yml from Template-Generic [skip ci] --- .mokogitea/workflows/auto-bump.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/auto-bump.yml b/.mokogitea/workflows/auto-bump.yml index 91e16f761d..b58ea7d24e 100644 --- a/.mokogitea/workflows/auto-bump.yml +++ b/.mokogitea/workflows/auto-bump.yml @@ -4,7 +4,7 @@ # # FILE INFORMATION # DEFGROUP: MokoGitea.Workflow -# INGROUP: mokocli.Release +# INGROUP: MokoCLI.Release # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # PATH: /.mokogitea/workflows/auto-bump.yml # VERSION: 09.02.00 @@ -44,7 +44,7 @@ jobs: token: ${{ secrets.MOKOGITEA_TOKEN }} fetch-depth: 1 - - name: Setup mokocli tools + - 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 @@ -53,7 +53,7 @@ jobs: 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" \ + "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" From 1a2e33abb356cae9cc587434c485eb02cb2eff1d Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 15:46:42 +0000 Subject: [PATCH 05/28] chore: sync auto-release.yml from Template-Generic [skip ci] --- .mokogitea/workflows/auto-release.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.mokogitea/workflows/auto-release.yml b/.mokogitea/workflows/auto-release.yml index a7563e0177..1b273e4503 100644 --- a/.mokogitea/workflows/auto-release.yml +++ b/.mokogitea/workflows/auto-release.yml @@ -4,17 +4,18 @@ # # FILE INFORMATION # DEFGROUP: MokoGitea.Workflow -# INGROUP: mokocli.Release +# INGROUP: MokoCLI.Release # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # PATH: /.mokogitea/workflows/auto-release.yml # VERSION: 05.01.00 -# BRIEF: Universal build & release � detects platform from manifest.xml +# BRIEF: Universal build & release � detects platform from the MokoGitea Metadata field (API) # # +=======================================================================+ # | UNIVERSAL BUILD & RELEASE PIPELINE | # +=======================================================================+ # | | -# | Reads manifest.xml (joomla|dolibarr|generic) to branch logic. | +# | Reads platform (joomla|dolibarr|generic) from the MokoGitea | +# | Metadata field (API) to branch logic. | # | | # | Platform-specific: | # | joomla: XML manifest, type-prefixed packages | @@ -81,7 +82,7 @@ jobs: fetch-depth: 1 submodules: recursive - - name: Setup mokocli tools + - name: Setup MokoCLI tools env: MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting @@ -95,7 +96,7 @@ jobs: sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1 fi rm -rf /tmp/mokocli - CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoCLI.git + CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli cd /tmp/mokocli composer install --no-dev --no-interaction --quiet @@ -231,7 +232,7 @@ jobs: fi echo "No conflict markers found" - - name: Setup mokocli tools + - name: Setup MokoCLI tools env: MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting @@ -246,7 +247,7 @@ jobs: sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1 fi rm -rf /tmp/mokocli - CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoCLI.git + CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli cd /tmp/mokocli composer install --no-dev --no-interaction --quiet From b0885f6da39d3d0c6cc9b5870e343f84c97016a3 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 15:46:48 +0000 Subject: [PATCH 06/28] chore: sync branch-cleanup.yml from Template-Generic [skip ci] --- .mokogitea/workflows/branch-cleanup.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mokogitea/workflows/branch-cleanup.yml b/.mokogitea/workflows/branch-cleanup.yml index 25ebae1e88..909e706839 100644 --- a/.mokogitea/workflows/branch-cleanup.yml +++ b/.mokogitea/workflows/branch-cleanup.yml @@ -4,7 +4,7 @@ # # FILE INFORMATION # DEFGROUP: MokoGitea.Workflow -# INGROUP: MokoStandards.Universal +# INGROUP: MokoCLI.Universal # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # PATH: /.mokogitea/workflows/branch-cleanup.yml # VERSION: 01.00.00 From fc66f8968f9dee9754c28005f88164eef0f67bef Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 15:46:55 +0000 Subject: [PATCH 07/28] chore: sync cascade-dev.yml from Template-Generic [skip ci] --- .mokogitea/workflows/cascade-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mokogitea/workflows/cascade-dev.yml b/.mokogitea/workflows/cascade-dev.yml index b2eabe15b1..31c35ad4c1 100644 --- a/.mokogitea/workflows/cascade-dev.yml +++ b/.mokogitea/workflows/cascade-dev.yml @@ -4,7 +4,7 @@ # # FILE INFORMATION # DEFGROUP: MokoGitea.Workflow -# INGROUP: MokoStandards.Cascade +# INGROUP: MokoCLI.Cascade # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # PATH: /.mokogitea/workflows/cascade-dev.yml # VERSION: 02.00.00 From a049052e5ae957a1106e892413a1db76bb201375 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 15:47:01 +0000 Subject: [PATCH 08/28] chore: sync ci-generic.yml from Template-Generic [skip ci] --- .mokogitea/workflows/ci-generic.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.mokogitea/workflows/ci-generic.yml b/.mokogitea/workflows/ci-generic.yml index 14f81bad5d..869087e4af 100644 --- a/.mokogitea/workflows/ci-generic.yml +++ b/.mokogitea/workflows/ci-generic.yml @@ -4,7 +4,7 @@ # # FILE INFORMATION # DEFGROUP: MokoGitea.Workflow -# INGROUP: MokoStandards.CI +# INGROUP: MokoCLI.CI # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # PATH: /.mokogitea/workflows/ci-generic.yml # VERSION: 01.00.00 @@ -131,7 +131,7 @@ jobs: test: name: Tests runs-on: ubuntu-latest - # Independent job (no `needs: lint`): the Gitea Actions scheduler does not + # Independent job (no `needs: lint`): the MokoGitea Actions scheduler does not # offer the dependent 2nd job of a needs-chain to runners, so it stalls in # "waiting" and is reaped by ABANDONED_JOB_TIMEOUT. Guard template repos # directly (same condition lint uses) instead of gating on lint's result. From 9496c7c42df56fd72b561bb15f20f5397f640677 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 15:47:08 +0000 Subject: [PATCH 09/28] chore: sync ci-issue-reporter.yml from Template-Generic [skip ci] --- .mokogitea/workflows/ci-issue-reporter.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.mokogitea/workflows/ci-issue-reporter.yml b/.mokogitea/workflows/ci-issue-reporter.yml index 0520237141..600d8c1df8 100644 --- a/.mokogitea/workflows/ci-issue-reporter.yml +++ b/.mokogitea/workflows/ci-issue-reporter.yml @@ -4,7 +4,7 @@ # # FILE INFORMATION # DEFGROUP: MokoGitea.Workflow -# INGROUP: mokocli.Universal +# INGROUP: MokoCLI.Universal # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # PATH: /.mokogitea/workflows/ci-issue-reporter.yml # VERSION: 01.00.00 @@ -52,7 +52,7 @@ jobs: 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 + 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 From c37ada7874110f8c485a36364ad231ab9fa754a9 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 15:47:16 +0000 Subject: [PATCH 10/28] chore: sync cleanup.yml from Template-Generic [skip ci] --- .mokogitea/workflows/cleanup.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.mokogitea/workflows/cleanup.yml b/.mokogitea/workflows/cleanup.yml index b4db32be6b..d08e29e554 100644 --- a/.mokogitea/workflows/cleanup.yml +++ b/.mokogitea/workflows/cleanup.yml @@ -4,8 +4,8 @@ # # FILE INFORMATION # DEFGROUP: MokoGitea.Workflow -# INGROUP: MokoStandards.Maintenance -# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards +# INGROUP: MokoCLI.Maintenance +# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli # PATH: /.mokogitea/workflows/cleanup.yml # VERSION: 01.00.00 # BRIEF: Scheduled cleanup — delete merged branches and old workflow runs From b902244949152aa86741d0a2643466d2d4ab5e96 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 15:47:24 +0000 Subject: [PATCH 11/28] chore: sync gitleaks.yml from Template-Generic [skip ci] --- .mokogitea/workflows/gitleaks.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.mokogitea/workflows/gitleaks.yml b/.mokogitea/workflows/gitleaks.yml index 7312838722..579f0cb374 100644 --- a/.mokogitea/workflows/gitleaks.yml +++ b/.mokogitea/workflows/gitleaks.yml @@ -4,8 +4,8 @@ # # FILE INFORMATION # DEFGROUP: MokoGitea.Workflow -# INGROUP: MokoStandards.Security -# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API +# INGROUP: MokoCLI.Security +# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli # PATH: /.mokogitea/workflows/gitleaks.yml # VERSION: 01.00.00 # BRIEF: Secret scanning — detect leaked credentials, API keys, and tokens From 1f0fe7012dfe327a7c1aec75edadba6e1bebba88 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 15:47:31 +0000 Subject: [PATCH 12/28] chore: sync issue-branch.yml from Template-Generic [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index eb67f8f7f8..12a4b11ff6 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -4,7 +4,7 @@ # # FILE INFORMATION # DEFGROUP: MokoGitea.Workflow -# INGROUP: mokocli.Automation +# INGROUP: MokoCLI.Automation # VERSION: 01.00.00 # BRIEF: Auto-create feature branch when an issue is opened From 5bc475e8f5c418ae892c8d7223a8caed070440bc Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 15:47:40 +0000 Subject: [PATCH 13/28] chore: sync notify.yml from Template-Generic [skip ci] --- .mokogitea/workflows/notify.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.mokogitea/workflows/notify.yml b/.mokogitea/workflows/notify.yml index 656996fbdc..7a03898512 100644 --- a/.mokogitea/workflows/notify.yml +++ b/.mokogitea/workflows/notify.yml @@ -4,8 +4,8 @@ # # FILE INFORMATION # DEFGROUP: MokoGitea.Workflow -# INGROUP: MokoStandards.Notifications -# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards +# INGROUP: MokoCLI.Notifications +# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli # PATH: /.mokogitea/workflows/notify.yml # VERSION: 01.00.00 # BRIEF: Push notifications via ntfy on release success or workflow failure From c0c121dfb5c7f7d774c70c81348422480737fcc8 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 15:47:47 +0000 Subject: [PATCH 14/28] chore: sync pr-check.yml from Template-Generic [skip ci] --- .mokogitea/workflows/pr-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mokogitea/workflows/pr-check.yml b/.mokogitea/workflows/pr-check.yml index 2874d60783..8fb052af7b 100644 --- a/.mokogitea/workflows/pr-check.yml +++ b/.mokogitea/workflows/pr-check.yml @@ -4,7 +4,7 @@ # # FILE INFORMATION # DEFGROUP: MokoGitea.Workflow -# INGROUP: mokocli.CI +# INGROUP: MokoCLI.CI # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # PATH: /.mokogitea/workflows/pr-check.yml # VERSION: 09.23.00 From 9e8d4c43bbeaa8ce0b2e9bca4978eafb32fc48d8 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 15:47:55 +0000 Subject: [PATCH 15/28] chore: sync pre-release.yml from Template-Generic [skip ci] --- .mokogitea/workflows/pre-release.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/pre-release.yml b/.mokogitea/workflows/pre-release.yml index b212772dda..4ea0367727 100644 --- a/.mokogitea/workflows/pre-release.yml +++ b/.mokogitea/workflows/pre-release.yml @@ -4,7 +4,7 @@ # # FILE INFORMATION # DEFGROUP: MokoGitea.Workflow -# INGROUP: mokocli.Release +# INGROUP: MokoCLI.Release # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # PATH: /.mokogitea/workflows/pre-release.yml # VERSION: 05.02.01 @@ -69,7 +69,7 @@ jobs: run: | git submodule foreach --quiet 'git checkout main && git pull --quiet origin main' 2>/dev/null || true - - name: Setup mokocli tools + - name: Setup MokoCLI tools env: MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting @@ -84,7 +84,7 @@ jobs: sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1 fi rm -rf /tmp/mokocli - CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoCLI.git + CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet echo MOKO_CLI=/tmp/mokocli/cli >> $GITHUB_ENV From 4972cf71bc016c9bb6cd78baeb2f7dad9160645f Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 15:48:03 +0000 Subject: [PATCH 16/28] chore: sync rc-revert.yml from Template-Generic [skip ci] --- .mokogitea/workflows/rc-revert.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mokogitea/workflows/rc-revert.yml b/.mokogitea/workflows/rc-revert.yml index 57934ea77d..f58d1fa02b 100644 --- a/.mokogitea/workflows/rc-revert.yml +++ b/.mokogitea/workflows/rc-revert.yml @@ -4,7 +4,7 @@ # # FILE INFORMATION # DEFGROUP: MokoGitea.Workflow -# INGROUP: mokocli.Universal +# INGROUP: MokoCLI.Universal # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # PATH: /.mokogitea/workflows/rc-revert.yml # VERSION: 09.23.00 From b5ce7fadccbf5e931133273acec68e9eda963bf0 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 15:48:11 +0000 Subject: [PATCH 17/28] chore: sync repo-health.yml from Template-Generic [skip ci] --- .mokogitea/workflows/repo-health.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mokogitea/workflows/repo-health.yml b/.mokogitea/workflows/repo-health.yml index 54d7cf9caf..3011fb777d 100644 --- a/.mokogitea/workflows/repo-health.yml +++ b/.mokogitea/workflows/repo-health.yml @@ -7,7 +7,7 @@ # # FILE INFORMATION # DEFGROUP: MokoGitea.Workflow -# INGROUP: mokocli.Validation +# INGROUP: MokoCLI.Validation # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # PATH: /.mokogitea/workflows/repo-health.yml # VERSION: 09.23.00 From 2d42b4e4752823c99dfbd99cb167f8856ed3d6b9 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 15:48:19 +0000 Subject: [PATCH 18/28] chore: sync sync-on-merge.yml from Template-Generic [skip ci] --- .mokogitea/workflows/sync-on-merge.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.mokogitea/workflows/sync-on-merge.yml b/.mokogitea/workflows/sync-on-merge.yml index e3622248b2..3bf0d3b025 100644 --- a/.mokogitea/workflows/sync-on-merge.yml +++ b/.mokogitea/workflows/sync-on-merge.yml @@ -12,10 +12,10 @@ jobs: runs-on: ubuntu-latest if: ${{ startsWith(github.event.repository.name, 'Template-') }} steps: - - name: Checkout mokocli + - name: Checkout MokoCLI uses: actions/checkout@v4 with: - repository: MokoConsulting/MokoCLI + repository: MokoConsulting/mokocli token: ${{ secrets.MOKOGITEA_TOKEN }} - name: Setup PHP From 485d6be31cab7e40746ce15b5e8857fd2123eda2 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 15:48:27 +0000 Subject: [PATCH 19/28] chore: sync version-set.yml from Template-Generic [skip ci] --- .mokogitea/workflows/version-set.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mokogitea/workflows/version-set.yml b/.mokogitea/workflows/version-set.yml index eed4192e4b..d7339bdce8 100644 --- a/.mokogitea/workflows/version-set.yml +++ b/.mokogitea/workflows/version-set.yml @@ -4,7 +4,7 @@ # # FILE INFORMATION # DEFGROUP: MokoGitea.Workflow.Template -# INGROUP: MokoStandards.CI +# INGROUP: MokoCLI.CI # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Joomla # PATH: /.mokogitea/workflows/version-set.yml # VERSION: 01.00.00 From f2dd391bca61751dd80975ea395f5a4c3ad00db7 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 15:48:35 +0000 Subject: [PATCH 20/28] chore: sync workflow-sync-trigger.yml from Template-Generic [skip ci] --- .mokogitea/workflows/workflow-sync-trigger.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/workflow-sync-trigger.yml b/.mokogitea/workflows/workflow-sync-trigger.yml index 69b00c422c..ccd9d584f1 100644 --- a/.mokogitea/workflows/workflow-sync-trigger.yml +++ b/.mokogitea/workflows/workflow-sync-trigger.yml @@ -4,7 +4,7 @@ # # FILE INFORMATION # DEFGROUP: MokoGitea.Workflow -# INGROUP: mokocli.Universal +# INGROUP: MokoCLI.Universal # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # PATH: /.mokogitea/workflows/workflow-sync-trigger.yml # VERSION: 01.01.00 @@ -48,12 +48,12 @@ jobs: echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT" echo "Platform: ${PLATFORM:-all}" - - name: Clone mokocli + - name: Clone MokoCLI env: MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} run: | MOKOGITEA_URL="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}" - git clone --depth 1 "${MOKOGITEA_URL}/MokoConsulting/MokoCLI.git" /tmp/mokocli + git clone --depth 1 "${MOKOGITEA_URL}/MokoConsulting/mokocli.git" /tmp/mokocli - name: Install PHP run: | From ae1aa3e21a9e6b330b0f1bd6362d63dbf4b41f02 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 15:58:20 +0000 Subject: [PATCH 21/28] chore: sync standards-compliance.yml from Template-Generic [skip ci] --- .mokogitea/workflows/standards-compliance.yml | 74 +++++++++---------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/.mokogitea/workflows/standards-compliance.yml b/.mokogitea/workflows/standards-compliance.yml index 7048eab9a9..c1339eb059 100644 --- a/.mokogitea/workflows/standards-compliance.yml +++ b/.mokogitea/workflows/standards-compliance.yml @@ -2,11 +2,11 @@ # SPDX-License-Identifier: GPL-3.0-or-later # FILE INFORMATION # DEFGROUP: GitHub.Workflow -# INGROUP: MokoStandards.Compliance -# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# INGROUP: MokoCLI.Compliance +# REPO: https://github.com/mokoconsulting-tech/mokocli # PATH: /.mokogitea/workflows/standards-compliance.yml # VERSION: 04.06.00 -# BRIEF: MokoStandards compliance validation workflow +# BRIEF: MokoCLI compliance validation workflow # NOTE: Validates repository structure, documentation, and coding standards name: "Generic: Standards Compliance" @@ -42,7 +42,7 @@ env: WORKFLOW_VERSION: "04.04.01" FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true -# MokoStandards Policy Compliance: +# MokoCLI Policy Compliance: # - File formatting: Enforces organizational coding standards # - Reference: docs/policy/file-formatting.md @@ -252,7 +252,7 @@ jobs: echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: LICENSE File Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Error:** LICENSE file is required for all MokoStandards-compliant repositories" >> $GITHUB_STEP_SUMMARY + echo "**Error:** LICENSE file is required for all MokoCLI-compliant repositories" >> $GITHUB_STEP_SUMMARY echo "**Action Required:** Add LICENSE file with appropriate open-source license (GPL-3.0-or-later recommended)" >> $GITHUB_STEP_SUMMARY echo "" echo "❌ ERROR: LICENSE file not found - This is a critical requirement" @@ -323,11 +323,11 @@ jobs: [ ! -d "docs" ] && echo "- Create docs directory: \`mkdir docs && echo '# Documentation' > docs/README.md\`" >> $GITHUB_STEP_SUMMARY [ ! -d ".github" ] && echo "- Create .github directory: \`mkdir -p .github/workflows\`" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "📚 Reference: [MokoStandards Repository Structure](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/core-structure.md)" >> $GITHUB_STEP_SUMMARY + echo "📚 Reference: [MokoCLI Repository Structure](https://github.com/mokoconsulting-tech/mokocli/tree/main/docs/policy/core-structure.md)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: Required Directories Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Status:** Repository structure does not meet MokoStandards requirements" >> $GITHUB_STEP_SUMMARY + echo "**Status:** Repository structure does not meet MokoCLI requirements" >> $GITHUB_STEP_SUMMARY echo "**Missing:** $MISSING required director(y|ies)" >> $GITHUB_STEP_SUMMARY echo "**Compliance:** $PERCENT% ($PRESENT/$TOTAL directories present)" >> $GITHUB_STEP_SUMMARY echo "" @@ -384,17 +384,17 @@ jobs: echo "### 🔴 Critical Issues: $MISSING" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Remediation Steps:**" >> $GITHUB_STEP_SUMMARY - [ ! -f "README.md" ] && echo "- Create README.md: Use [template](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/templates/docs/required/README.md)" >> $GITHUB_STEP_SUMMARY + [ ! -f "README.md" ] && echo "- Create README.md: Use [template](https://github.com/mokoconsulting-tech/mokocli/tree/main/templates/docs/required/README.md)" >> $GITHUB_STEP_SUMMARY [ ! -f "LICENSE" ] && echo "- Add LICENSE file: Choose from [OSI-approved licenses](https://opensource.org/licenses)" >> $GITHUB_STEP_SUMMARY - [ ! -f "CONTRIBUTING.md" ] && echo "- Create CONTRIBUTING.md: Use [template](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/templates/docs/required/CONTRIBUTING.md)" >> $GITHUB_STEP_SUMMARY - [ ! -f "SECURITY.md" ] && echo "- Create SECURITY.md: Use [template](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/templates/docs/required/SECURITY.md)" >> $GITHUB_STEP_SUMMARY - [ ! -f ".editorconfig" ] && echo "- Add .editorconfig: Use [template](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/templates/.editorconfig)" >> $GITHUB_STEP_SUMMARY + [ ! -f "CONTRIBUTING.md" ] && echo "- Create CONTRIBUTING.md: Use [template](https://github.com/mokoconsulting-tech/mokocli/tree/main/templates/docs/required/CONTRIBUTING.md)" >> $GITHUB_STEP_SUMMARY + [ ! -f "SECURITY.md" ] && echo "- Create SECURITY.md: Use [template](https://github.com/mokoconsulting-tech/mokocli/tree/main/templates/docs/required/SECURITY.md)" >> $GITHUB_STEP_SUMMARY + [ ! -f ".editorconfig" ] && echo "- Add .editorconfig: Use [template](https://github.com/mokoconsulting-tech/mokocli/tree/main/templates/.editorconfig)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "📚 Reference: [MokoStandards File Requirements](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/file-header-standards.md)" >> $GITHUB_STEP_SUMMARY + echo "📚 Reference: [MokoCLI File Requirements](https://github.com/mokoconsulting-tech/mokocli/tree/main/docs/policy/file-header-standards.md)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: Required Files Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Status:** Repository files do not meet MokoStandards requirements" >> $GITHUB_STEP_SUMMARY + echo "**Status:** Repository files do not meet MokoCLI requirements" >> $GITHUB_STEP_SUMMARY echo "**Missing:** $MISSING required file(s)" >> $GITHUB_STEP_SUMMARY echo "**Compliance:** $PERCENT% ($PRESENT/$TOTAL files present)" >> $GITHUB_STEP_SUMMARY echo "" @@ -437,7 +437,7 @@ jobs: echo "$TABS_IN_SPACES_FILES" >> $GITHUB_STEP_SUMMARY echo "\`\`\`" >> $GITHUB_STEP_SUMMARY echo "These languages require spaces (tabs will break): YAML, Python, Haskell, F#, CoffeeScript, Nim, JSON, RST" >> $GITHUB_STEP_SUMMARY - echo "All other files (including .md, .ps1, LICENSE, etc.) may use tabs per MokoStandards policy" >> $GITHUB_STEP_SUMMARY + echo "All other files (including .md, .ps1, LICENSE, etc.) may use tabs per MokoCLI policy" >> $GITHUB_STEP_SUMMARY else echo "✅ No tabs found in files requiring spaces" >> $GITHUB_STEP_SUMMARY echo "Note: Tabs are allowed in most files (policy default). Only checked files requiring spaces." >> $GITHUB_STEP_SUMMARY @@ -483,7 +483,7 @@ jobs: echo "\`\`\`" >> $GITHUB_STEP_SUMMARY echo "$CRLF_FILES" >> $GITHUB_STEP_SUMMARY echo "\`\`\`" >> $GITHUB_STEP_SUMMARY - echo "MokoStandards requires LF line endings" >> $GITHUB_STEP_SUMMARY + echo "MokoCLI requires LF line endings" >> $GITHUB_STEP_SUMMARY else echo "✅ Line endings are consistent (LF)" >> $GITHUB_STEP_SUMMARY fi @@ -504,13 +504,13 @@ jobs: tools: composer coverage: none - - name: Setup MokoStandards tools + - name: Setup MokoCLI tools env: GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }} COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}' run: | git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/mokocli.git" \ /tmp/mokostandards 2>/dev/null || true if [ -d "/tmp/mokostandards" ] && [ -f "/tmp/mokostandards/composer.json" ]; then cd /tmp/mokostandards @@ -524,7 +524,7 @@ jobs: echo "## 🔢 Version Consistency Validation" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - # Use MokoStandards tools (no Composer needed on the governed repo) + # Use MokoCLI tools (no Composer needed on the governed repo) if [ -f "/tmp/mokostandards/api/validate/check_version_consistency.php" ]; then php /tmp/mokostandards/api/validate/check_version_consistency.php --path . --verbose 2>&1 | tee /tmp/version-check.log EXIT_CODE=${PIPESTATUS[0]} @@ -532,7 +532,7 @@ jobs: php api/validate/check_version_consistency.php --path . --verbose 2>&1 | tee /tmp/version-check.log EXIT_CODE=${PIPESTATUS[0]} else - echo "⏭️ MokoStandards tools not available — skipping version check" >> $GITHUB_STEP_SUMMARY + echo "⏭️ MokoCLI tools not available — skipping version check" >> $GITHUB_STEP_SUMMARY exit 0 fi @@ -597,12 +597,12 @@ jobs: echo "⚠️ CodeQL workflow not found" >> $GITHUB_STEP_SUMMARY fi - # Check for MokoStandards-synced workflows + # Check for MokoCLI-synced workflows for wf in deploy-dev.yml deploy-demo.yml deploy-rs.yml sync-version-on-merge.yml auto-release.yml standards-compliance.yml enterprise-firewall-setup.yml; do if [ -f "$WORKFLOWS_DIR/$wf" ]; then echo "✅ ${wf}" >> $GITHUB_STEP_SUMMARY else - echo "⚠️ ${wf} not found (synced from MokoStandards)" >> $GITHUB_STEP_SUMMARY + echo "⚠️ ${wf} not found (synced from MokoCLI)" >> $GITHUB_STEP_SUMMARY fi done @@ -809,7 +809,7 @@ jobs: echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: README.md Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Error:** README.md is required for all MokoStandards-compliant repositories" >> $GITHUB_STEP_SUMMARY + echo "**Error:** README.md is required for all MokoCLI-compliant repositories" >> $GITHUB_STEP_SUMMARY echo "**Action Required:** Create README.md with project description, setup instructions, and usage examples" >> $GITHUB_STEP_SUMMARY echo "" echo "❌ ERROR: README.md not found - This is a critical requirement" @@ -915,7 +915,7 @@ jobs: echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: CHANGELOG.md Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Error:** CHANGELOG.md is required for all MokoStandards-compliant repositories" >> $GITHUB_STEP_SUMMARY + echo "**Error:** CHANGELOG.md is required for all MokoCLI-compliant repositories" >> $GITHUB_STEP_SUMMARY echo "**Action Required:** Create CHANGELOG.md following [Keep a Changelog](https://keepachangelog.com/) format" >> $GITHUB_STEP_SUMMARY echo "" echo "❌ ERROR: CHANGELOG.md not found - This is a critical requirement" @@ -1976,10 +1976,10 @@ jobs: if [ -f "composer.json" ]; then composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader else - echo "No composer.json — pulling MokoStandards tools" + echo "No composer.json — pulling MokoCLI tools" if [ ! -d "/tmp/mokostandards" ]; then git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/mokocli.git" \ /tmp/mokostandards 2>/dev/null || true if [ -f "/tmp/mokostandards/composer.json" ]; then cd /tmp/mokostandards && composer install --no-dev --no-interaction --quiet 2>/dev/null || true @@ -2048,10 +2048,10 @@ jobs: if [ -f "composer.json" ]; then composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader else - echo "No composer.json — pulling MokoStandards tools" + echo "No composer.json — pulling MokoCLI tools" if [ ! -d "/tmp/mokostandards" ]; then git clone --depth 1 --branch version/04 --quiet \ - "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \ + "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/mokocli.git" \ /tmp/mokostandards 2>/dev/null || true if [ -f "/tmp/mokostandards/composer.json" ]; then cd /tmp/mokostandards && composer install --no-dev --no-interaction --quiet 2>/dev/null || true @@ -2133,7 +2133,7 @@ jobs: # 1. Check .github/config.tf location (not root override files) echo "### Override Configuration Check" >> $GITHUB_STEP_SUMMARY - LEGACY_OVERRIDES=$(find . -maxdepth 1 -name "*override*.tf" -o -name "MokoStandards.override.tf" 2>/dev/null | wc -l || echo 0) + LEGACY_OVERRIDES=$(find . -maxdepth 1 -name "*override*.tf" -o -name "MokoCLI.override.tf" 2>/dev/null | wc -l || echo 0) if [ "$LEGACY_OVERRIDES" -gt 0 ]; then echo "⚠️ Found legacy override files in root directory" >> $GITHUB_STEP_SUMMARY echo "**Expected Location**: .github/config.tf" >> $GITHUB_STEP_SUMMARY @@ -2299,7 +2299,7 @@ jobs: - name: Generate Compliance Report run: | set -x - echo "# 📊 MokoStandards Compliance Report" >> $GITHUB_STEP_SUMMARY + echo "# 📊 MokoCLI Compliance Report" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY # Calculate overall status @@ -2486,7 +2486,7 @@ jobs: else echo "## 🎉 Excellent!" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "Your repository is **fully compliant** with MokoStandards!" >> $GITHUB_STEP_SUMMARY + echo "Your repository is **fully compliant** with MokoCLI!" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Achievements:**" >> $GITHUB_STEP_SUMMARY echo "- ✅ All required directories and files present" >> $GITHUB_STEP_SUMMARY @@ -2501,12 +2501,12 @@ jobs: echo "---" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "📚 **Resources:**" >> $GITHUB_STEP_SUMMARY - echo "- [MokoStandards Documentation](https://github.com/mokoconsulting-tech/MokoStandards)" >> $GITHUB_STEP_SUMMARY - echo "- [Repository Structure Guide](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/core-structure.md)" >> $GITHUB_STEP_SUMMARY - echo "- [Documentation Standards](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/document-formatting.md)" >> $GITHUB_STEP_SUMMARY - echo "- [Coding Standards](https://github.com/mokoconsulting-tech/MokoStandards/tree/main/docs/policy/coding-style-guide.md)" >> $GITHUB_STEP_SUMMARY + echo "- [MokoCLI Documentation](https://github.com/mokoconsulting-tech/mokocli)" >> $GITHUB_STEP_SUMMARY + echo "- [Repository Structure Guide](https://github.com/mokoconsulting-tech/mokocli/tree/main/docs/policy/core-structure.md)" >> $GITHUB_STEP_SUMMARY + echo "- [Documentation Standards](https://github.com/mokoconsulting-tech/mokocli/tree/main/docs/policy/document-formatting.md)" >> $GITHUB_STEP_SUMMARY + echo "- [Coding Standards](https://github.com/mokoconsulting-tech/mokocli/tree/main/docs/policy/coding-style-guide.md)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "_Generated by MokoStandards Compliance Workflow v${WORKFLOW_VERSION}_" >> $GITHUB_STEP_SUMMARY + echo "_Generated by MokoCLI Compliance Workflow v${WORKFLOW_VERSION}_" >> $GITHUB_STEP_SUMMARY # Create tracking issue for non-compliance if on push if [ "$COMPLIANCE_PERCENT" -lt 100 ] && [ "${{ github.event_name }}" = "push" ]; then @@ -2530,9 +2530,9 @@ jobs: echo "### ✅ Full Standards Compliance Achieved" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Overall Compliance:** 100%" >> $GITHUB_STEP_SUMMARY - echo "**Status:** Repository meets all MokoStandards requirements" >> $GITHUB_STEP_SUMMARY + echo "**Status:** Repository meets all MokoCLI requirements" >> $GITHUB_STEP_SUMMARY echo "" - echo "✅ SUCCESS: Repository is fully MokoStandards compliant" + echo "✅ SUCCESS: Repository is fully MokoCLI compliant" - name: Create or reopen tracking issue for standards violations if: failure() From 0a66dacb86e5f39046814a53bee7e5bdbc43ea29 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 16:21:45 +0000 Subject: [PATCH 22/28] chore: sync auto-release.yml from Template-Generic [skip ci] --- .mokogitea/workflows/auto-release.yml | 76 +++++++++++++++++++-------- 1 file changed, 53 insertions(+), 23 deletions(-) diff --git a/.mokogitea/workflows/auto-release.yml b/.mokogitea/workflows/auto-release.yml index 1b273e4503..ee87c5636f 100644 --- a/.mokogitea/workflows/auto-release.yml +++ b/.mokogitea/workflows/auto-release.yml @@ -8,14 +8,13 @@ # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # PATH: /.mokogitea/workflows/auto-release.yml # VERSION: 05.01.00 -# BRIEF: Universal build & release � detects platform from the MokoGitea Metadata field (API) +# BRIEF: Universal build & release � detects platform from metadata API # # +=======================================================================+ # | UNIVERSAL BUILD & RELEASE PIPELINE | # +=======================================================================+ # | | -# | Reads platform (joomla|dolibarr|generic) from the MokoGitea | -# | Metadata field (API) to branch logic. | +# | Reads metadata API (joomla|dolibarr|generic) to branch logic. | # | | # | Platform-specific: | # | joomla: XML manifest, type-prefixed packages | @@ -116,20 +115,17 @@ jobs: SRC_SHA=$(printf '%s' "$SRC_JSON" | python3 -c "import sys, json; print(json.load(sys.stdin)['commit']['id'])" 2>/dev/null || true) [ -n "$SRC_SHA" ] || { echo "::error::Could not resolve HEAD of ${FROM}"; exit 1; } - # Point rc at the source commit. If rc already exists (a protected branch that - # cannot be deleted), force-update its ref in place instead of delete+recreate: - # deleting a protected branch fails, which then makes the recreate return HTTP 409. - if curl -sf -o /dev/null -H "$AUTH" "${API_BASE}/branches/rc"; then - echo "rc exists - force-updating to ${FROM} (${SRC_SHA})" - curl -sf -X PATCH -H "$AUTH" -H "Content-Type: application/json" \ - "${API_BASE}/git/refs/heads/rc" -d "{\"sha\":\"${SRC_SHA}\",\"force\":true}" \ - || { echo "::error::Failed to force-update rc (CI token needs force-push on the protected rc branch)"; exit 1; } - else - echo "Creating rc from ${FROM}" - curl -sf -X POST -H "$AUTH" -H "Content-Type: application/json" \ - "${API_BASE}/branches" -d "{\"new_branch_name\":\"rc\",\"old_branch_name\":\"${FROM}\"}" \ - || { echo "::error::Failed to create rc from ${FROM}"; exit 1; } - fi + # Point rc at the source commit via git push. Gitea's git/refs PATCH API + # returns HTTP 405 on ANY protected branch (force or not, even for a user in + # the force-push allowlist), so it cannot move a protected rc. git push honors + # the push + force-push allowlists and creates rc if it is absent. + PUSH_URL="https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@${MOKOGITEA_URL#https://}/${GITEA_ORG}/${GITEA_REPO}.git" + git config --global user.name "mokogitea-actions[bot]" + git config --global user.email "actions@mokoconsulting.tech" + git fetch --no-tags "$PUSH_URL" "${FROM}" + git push --force "$PUSH_URL" "FETCH_HEAD:refs/heads/rc" \ + || { echo "::error::Failed to point rc at ${FROM} (${SRC_SHA}) via git push"; exit 1; } + echo "rc set to ${FROM} (${SRC_SHA})" # Repoint the PR at rc, then delete the old source branch (non-fatal). if [ -n "$PR" ]; then @@ -378,13 +374,47 @@ jobs: if [ -n "$VERSION" ] && [ -f "CHANGELOG.md" ]; then DATE=$(date +%Y-%m-%d) python3 -c " - import sys + import sys, re version, date = sys.argv[1], sys.argv[2] - content = open('CHANGELOG.md').read() - old = '## [Unreleased]' - new = f'## [Unreleased]\n\n## [{version}] --- {date}' - content = content if ('## [' + version + ']') in content else content.replace(old, new, 1) - open('CHANGELOG.md', 'w').write(content) + lines = open('CHANGELOG.md').read().split('\n') + h2 = re.compile(r'^##\s+\[([^\]]+)\]') + header, sections, cur = [], [], None + for ln in lines: + m = h2.match(ln) + if m: + if cur: sections.append(cur) + cur = {'label': m.group(1).strip(), 'head': ln, 'body': []} + elif cur is None: + header.append(ln) + else: + cur['body'].append(ln) + if cur: sections.append(cur) + def nonempty(b): return any(x.strip() for x in b) + def trim(b): + b = b[:] + while b and not b[0].strip(): b.pop(0) + while b and not b[-1].strip(): b.pop() + return b + unreleased, order, bykey = [], [], {} + for s in sections: + key = s['label'].lower() + if key == 'unreleased': + if nonempty(s['body']): unreleased += s['body'] + continue + if not nonempty(s['body']): continue # drop blank release sections + if key in bykey: bykey[key]['body'] += [''] + s['body'] # merge duplicate heading (never drop content) + else: bykey[key] = s; order.append(key) + rest, seen = [bykey[k] for k in order], set(order) + out = [] + htxt = '\n'.join(header).rstrip() + if htxt: out += [htxt, ''] + out += ['## [Unreleased]', ''] + promote = bool(unreleased) and version.lower() not in seen + if unreleased and not promote: out += trim(unreleased) + [''] + if promote: out += ['## [%s] --- %s' % (version, date), ''] + trim(unreleased) + [''] + for s in rest: out += [s['head'], ''] + trim(s['body']) + [''] + res = re.sub(r'\n{3,}', '\n\n', '\n'.join(out)).rstrip('\n') + '\n' + open('CHANGELOG.md', 'w').write(res) " "$VERSION" "$DATE" git add CHANGELOG.md git commit -m "chore: promote changelog [Unreleased] → [${VERSION}]" || true From 66017e166889f694c97b812faa1b2e515cb30d13 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 16:21:51 +0000 Subject: [PATCH 23/28] chore: sync cascade-dev.yml from Template-Generic [skip ci] --- .mokogitea/workflows/cascade-dev.yml | 128 ++++++++++++++++++++++----- 1 file changed, 106 insertions(+), 22 deletions(-) diff --git a/.mokogitea/workflows/cascade-dev.yml b/.mokogitea/workflows/cascade-dev.yml index 31c35ad4c1..8ae17c44ff 100644 --- a/.mokogitea/workflows/cascade-dev.yml +++ b/.mokogitea/workflows/cascade-dev.yml @@ -7,8 +7,8 @@ # INGROUP: MokoCLI.Cascade # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # PATH: /.mokogitea/workflows/cascade-dev.yml -# VERSION: 02.00.00 -# BRIEF: Cascade main -> dev via PR; auto-merge only if conflict-free, else notify +# VERSION: 02.01.00 +# BRIEF: Cascade main -> dev; auto-merge clean, auto-resolve VERSION-stamp-only conflicts, else notify name: "Cascade Main -> Dev" @@ -16,6 +16,10 @@ on: push: branches: - main + # Daily safety net: catches drift even when main only received [skip ci] pushes + # (which never fire the push trigger above). Off-round minute to avoid a fleet-wide spike. + schedule: + - cron: '23 7 * * *' workflow_dispatch: permissions: @@ -33,7 +37,13 @@ jobs: name: Cascade main -> dev runs-on: ubuntu-latest steps: - - name: Open main -> dev PR (auto-merge if clean, else notify) + - name: Checkout (full history for merge/resolve) + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.MOKOGITEA_TOKEN }} + + - name: Cascade main -> dev (auto-resolve version stamps, else notify) env: TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} REPO: ${{ github.repository }} @@ -41,7 +51,7 @@ jobs: set -uo pipefail API="${MOKOGITEA_URL}/api/v1/repos/${REPO}" AUTH="Authorization: token ${TOKEN}" - jqnum() { python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('$1',''))" 2>/dev/null; } + jqget() { python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('$1',''))" 2>/dev/null; } # 0. dev must exist if ! curl -sf -H "$AUTH" "${API}/branches/dev" >/dev/null 2>&1; then @@ -61,8 +71,8 @@ jobs: | python3 -c "import sys,json; d=json.load(sys.stdin); print(next((str(p['number']) for p in d if p.get('head',{}).get('ref')=='main'), ''))" 2>/dev/null || echo "") if [ -z "$PR" ]; then RESP=$(curl -s -H "$AUTH" -H "Content-Type: application/json" -X POST "${API}/pulls" \ - -d '{"head":"main","base":"dev","title":"chore(sync): cascade main -> dev","body":"Automated cascade of main into dev. Auto-merges only if conflict-free; otherwise left open for manual resolution."}') - PR=$(printf '%s' "$RESP" | jqnum number) + -d '{"head":"main","base":"dev","title":"chore(sync): cascade main -> dev","body":"Automated cascade of main into dev. Auto-merges when conflict-free, auto-resolves VERSION-stamp-only conflicts, otherwise left open for manual resolution."}') + PR=$(printf '%s' "$RESP" | jqget number) if [ -z "$PR" ]; then echo "::warning::Could not open cascade PR: $RESP"; exit 0 fi @@ -71,15 +81,6 @@ jobs: echo "Reusing open cascade PR #${PR}" fi - # 3. wait for MokoGitea to compute mergeability (conflict detection) - MERGEABLE="" - for _ in 1 2 3 4 5 6; do - MERGEABLE=$(curl -sf -H "$AUTH" "${API}/pulls/${PR}" | jqnum mergeable) - case "$MERGEABLE" in True|False) break ;; esac - sleep 3 - done - echo "mergeable=${MERGEABLE}" - notify() { curl -sS \ -H "Title: ${REPO}: dev cascade needs manual merge" \ @@ -90,17 +91,100 @@ jobs: "${NTFY_URL}/${NTFY_TOPIC}" || true } - # 4. auto-merge only if conflict-free; otherwise notify + # 3. wait for MokoGitea to compute mergeability (conflict detection) + MERGEABLE="" + for _ in 1 2 3 4 5 6; do + MERGEABLE=$(curl -sf -H "$AUTH" "${API}/pulls/${PR}" | jqget mergeable) + case "$MERGEABLE" in True|False) break ;; esac + sleep 3 + done + echo "mergeable=${MERGEABLE}" + + # 4a. conflict-free -> merge via API (existing behaviour) if [ "$MERGEABLE" = "True" ]; then CODE=$(curl -s -o /tmp/merge.json -w "%{http_code}" -H "$AUTH" -H "Content-Type: application/json" \ -X POST "${API}/pulls/${PR}/merge" -d '{"Do":"merge","merge_when_checks_succeed":true}') if [ "$CODE" -ge 200 ] && [ "$CODE" -lt 300 ]; then echo "Cascade PR #${PR} merged (or scheduled to merge when checks pass)." - else - echo "::warning::Auto-merge returned HTTP ${CODE}: $(cat /tmp/merge.json)" - notify "could not be auto-merged (HTTP ${CODE})." + exit 0 fi - else - echo "::warning::Cascade PR #${PR} has conflicts (mergeable=${MERGEABLE}); sending notification." - notify "has conflicts and cannot be merged automatically." + echo "::warning::Auto-merge returned HTTP ${CODE}: $(cat /tmp/merge.json)" + notify "could not be auto-merged (HTTP ${CODE})." + exit 0 fi + + # 4b. conflicts -> try to auto-resolve if they are ONLY VERSION-stamp lines. + echo "PR not cleanly mergeable; checking whether conflicts are VERSION-stamp-only..." + git config user.name "MokoGitea Cascade" + git config user.email "actions@mokoconsulting.tech" + git fetch --quiet origin main dev + git checkout -B dev origin/dev + + if git merge --no-ff --no-commit origin/main >/dev/null 2>&1; then + # Became clean at git level (e.g. mergeability was still computing) -> commit + push. + git commit -m "chore(sync): cascade main -> dev [skip ci]" >/dev/null + git push origin dev + echo "Cascade merged cleanly at git level and pushed to dev." + exit 0 + fi + + CONFLICTS=$(git diff --name-only --diff-filter=U) + echo "Conflicted files:"; echo "${CONFLICTS}" + + # A conflict is "stamp-only" when every line inside every conflict block matches + # a version-stamp pattern (VERSION: header, element, or CHANGELOG title). + is_stamp_only() { + awk ' + /^<<<<<<< / { inc=1; next } + inc && /^=======$/ { next } + /^>>>>>>> / { inc=0; next } + inc { if ($0 !~ /(VERSION:||# Changelog)/) { bad=1 } } + END { exit(bad ? 1 : 0) } + ' "$1" + } + # Resolve a stamp-only file by keeping dev (ours) for the conflicting lines, + # preserving all auto-merged content around them. + keep_ours() { + awk ' + /^<<<<<<< / { inc=1; side="ours"; next } + inc && /^=======$/ { side="theirs"; next } + /^>>>>>>> / { inc=0; next } + { if (!inc) { print; next } if (side=="ours") print } + ' "$1" > "$1.resolved" && mv "$1.resolved" "$1" + } + + ALL_STAMP=1 + for f in ${CONFLICTS}; do + if ! is_stamp_only "$f"; then + echo "::notice::$f has non-stamp conflicts -> manual resolution required." + ALL_STAMP=0; break + fi + done + + if [ "$ALL_STAMP" != "1" ]; then + git merge --abort || true + notify "has non-version-stamp conflicts and cannot be auto-resolved." + exit 0 + fi + + echo "All conflicts are VERSION-stamp-only; resolving in favour of dev." + for f in ${CONFLICTS}; do + keep_ours "$f" + git add "$f" + done + + # Best-effort: normalise stamps to dev's version if mokocli is available. + if [ -f /opt/mokocli/cli/version_check.php ]; then + php /opt/mokocli/cli/version_check.php --fix || true + git add -A + fi + + git commit -m "chore(sync): cascade main -> dev (auto-resolved version stamps) [skip ci]" >/dev/null + git push origin dev + echo "Cascade auto-resolved and pushed to dev." + + # Close the now-redundant PR (its changes are in dev) with an explanatory comment. + curl -s -H "$AUTH" -H "Content-Type: application/json" -X POST "${API}/issues/${PR}/comments" \ + -d '{"body":"Auto-resolved VERSION-stamp-only conflicts and pushed the merge to dev. Closing."}' >/dev/null || true + curl -s -H "$AUTH" -H "Content-Type: application/json" -X PATCH "${API}/pulls/${PR}" \ + -d '{"state":"closed"}' >/dev/null || true From affba0a2cd0a97f027e86af41ceec6baf9388cd8 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 16:21:58 +0000 Subject: [PATCH 24/28] chore: sync pr-check.yml from Template-Generic [skip ci] --- .mokogitea/workflows/pr-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mokogitea/workflows/pr-check.yml b/.mokogitea/workflows/pr-check.yml index 8fb052af7b..6da762a8c0 100644 --- a/.mokogitea/workflows/pr-check.yml +++ b/.mokogitea/workflows/pr-check.yml @@ -224,7 +224,7 @@ jobs: - name: Detect platform id: platform run: | - # Platform comes from the MokoGitea metadata API (public GET); manifest.xml is no longer used. + # Platform comes from the MokoGitea metadata API (public GET). API="${GITHUB_SERVER_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${GITHUB_REPOSITORY}/metadata" PLATFORM="$(curl -sf "$API" 2>/dev/null | python3 -c "import sys, json; print(json.load(sys.stdin).get('platform') or '')" 2>/dev/null || true)" [ -z "$PLATFORM" ] && PLATFORM="generic" From 0fc4adf1a71454fead521aa189d09a3911111467 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 19:51:27 +0000 Subject: [PATCH 25/28] chore: sync standards-compliance.yml from Template-Generic [skip ci] --- .mokogitea/workflows/standards-compliance.yml | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/.mokogitea/workflows/standards-compliance.yml b/.mokogitea/workflows/standards-compliance.yml index c1339eb059..2a7abc38e9 100644 --- a/.mokogitea/workflows/standards-compliance.yml +++ b/.mokogitea/workflows/standards-compliance.yml @@ -291,7 +291,7 @@ jobs: MISSING=0 PRESENT=0 - TOTAL=2 + TOTAL=1 echo "### Required Directories" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY @@ -299,7 +299,7 @@ jobs: echo "|-----------|--------|-------|------|-------|" >> $GITHUB_STEP_SUMMARY # Check required directories - for dir in docs .github; do + for dir in .mokogitea; do if [ -d "$dir" ]; then FILE_COUNT=$(find "$dir" -type f 2>/dev/null | wc -l) DIR_SIZE=$(du -sh "$dir" 2>/dev/null | cut -f1) @@ -320,8 +320,7 @@ jobs: echo "### 🔴 Critical Issues: $MISSING" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Remediation Steps:**" >> $GITHUB_STEP_SUMMARY - [ ! -d "docs" ] && echo "- Create docs directory: \`mkdir docs && echo '# Documentation' > docs/README.md\`" >> $GITHUB_STEP_SUMMARY - [ ! -d ".github" ] && echo "- Create .github directory: \`mkdir -p .github/workflows\`" >> $GITHUB_STEP_SUMMARY + [ ! -d ".mokogitea" ] && echo "- Create .mokogitea directory: \`mkdir -p .mokogitea/workflows\`" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "📚 Reference: [MokoCLI Repository Structure](https://github.com/mokoconsulting-tech/mokocli/tree/main/docs/policy/core-structure.md)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY @@ -564,17 +563,17 @@ jobs: set -x echo "### GitHub Actions Workflows" >> $GITHUB_STEP_SUMMARY - WORKFLOWS_DIR=".github/workflows" + WORKFLOWS_DIR=".mokogitea/workflows" if [ ! -d "$WORKFLOWS_DIR" ]; then echo "❌ No workflows directory found" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### ❌ Validation Failed: Workflows Directory Missing" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Error:** .github/workflows directory is required for CI/CD automation" >> $GITHUB_STEP_SUMMARY - echo "**Action Required:** Create .github/workflows directory and add GitHub Actions workflows" >> $GITHUB_STEP_SUMMARY + echo "**Error:** .mokogitea/workflows directory is required for CI/CD automation" >> $GITHUB_STEP_SUMMARY + echo "**Action Required:** Create .mokogitea/workflows directory and add GitHub Actions workflows" >> $GITHUB_STEP_SUMMARY echo "" - echo "❌ ERROR: .github/workflows directory not found" + echo "❌ ERROR: .mokogitea/workflows directory not found" exit 1 fi @@ -613,7 +612,7 @@ jobs: echo "### Workflow YAML Syntax" >> $GITHUB_STEP_SUMMARY INVALID=0 - for workflow in $(find .github/workflows -maxdepth 1 -type f \( -name "*.yml" -o -name "*.yaml" \) 2>/dev/null); do + for workflow in $(find .mokogitea/workflows -maxdepth 1 -type f \( -name "*.yml" -o -name "*.yaml" \) 2>/dev/null); do if [ -f "$workflow" ]; then if python3 -c "import yaml, sys; yaml.safe_load(open(sys.argv[1]))" "$workflow" 2>/dev/null; then echo "✅ $(basename $workflow)" >> $GITHUB_STEP_SUMMARY @@ -630,7 +629,7 @@ jobs: echo "" >> $GITHUB_STEP_SUMMARY echo "**Error:** $INVALID workflow file(s) have invalid YAML syntax" >> $GITHUB_STEP_SUMMARY echo "**Action Required:** Fix YAML syntax errors in the marked workflow files" >> $GITHUB_STEP_SUMMARY - echo "**Tool:** Run \`python3 -c \"import yaml; yaml.safe_load(open('.github/workflows/FILE.yml'))\"\` locally" >> $GITHUB_STEP_SUMMARY + echo "**Tool:** Run \`python3 -c \"import yaml; yaml.safe_load(open('.mokogitea/workflows/FILE.yml'))\"\` locally" >> $GITHUB_STEP_SUMMARY echo "" echo "❌ ERROR: $INVALID workflow file(s) with invalid YAML syntax" exit 1 @@ -642,7 +641,7 @@ jobs: echo "✅ SUCCESS: All workflow files passed YAML validation" - name: Validate CodeQL Configuration - if: hashFiles('.github/workflows/codeql-analysis.yml') != '' + if: hashFiles('.mokogitea/workflows/codeql-analysis.yml') != '' run: | set -e echo "" >> $GITHUB_STEP_SUMMARY @@ -650,7 +649,7 @@ jobs: echo "" >> $GITHUB_STEP_SUMMARY # Inline validation (rewritten from Python to bash for PHP-only architecture) - CODEQL_FILE=".github/workflows/codeql-analysis.yml" + CODEQL_FILE=".mokogitea/workflows/codeql-analysis.yml" if [ ! -f "$CODEQL_FILE" ]; then echo "⚠️ CodeQL workflow file not found" >> $GITHUB_STEP_SUMMARY @@ -1187,7 +1186,7 @@ jobs: fi # Run yamllint and count line-length warnings - YAML_OUTPUT=$(yamllint .github/workflows/*.yml 2>&1 | grep "line too long" || true) + YAML_OUTPUT=$(yamllint .mokogitea/workflows/*.yml 2>&1 | grep "line too long" || true) if [ -n "$YAML_OUTPUT" ]; then YAML_VIOLATIONS=$(echo "$YAML_OUTPUT" | wc -l) echo "⚠️ Found $YAML_VIOLATIONS lines exceeding 180 characters in YAML files" >> $GITHUB_STEP_SUMMARY @@ -2131,17 +2130,17 @@ jobs: WARNINGS=0 ERRORS=0 - # 1. Check .github/config.tf location (not root override files) + # 1. Check .mokogitea/config.tf location (not root override files) echo "### Override Configuration Check" >> $GITHUB_STEP_SUMMARY LEGACY_OVERRIDES=$(find . -maxdepth 1 -name "*override*.tf" -o -name "MokoCLI.override.tf" 2>/dev/null | wc -l || echo 0) if [ "$LEGACY_OVERRIDES" -gt 0 ]; then echo "⚠️ Found legacy override files in root directory" >> $GITHUB_STEP_SUMMARY - echo "**Expected Location**: .github/config.tf" >> $GITHUB_STEP_SUMMARY + echo "**Expected Location**: .mokogitea/config.tf" >> $GITHUB_STEP_SUMMARY echo "**Legacy files found**: $LEGACY_OVERRIDES" >> $GITHUB_STEP_SUMMARY WARNINGS=$((WARNINGS + 1)) else - if [ -f ".github/config.tf" ]; then - echo "✅ Override configuration in correct location (.github/config.tf)" >> $GITHUB_STEP_SUMMARY + if [ -f ".mokogitea/config.tf" ]; then + echo "✅ Override configuration in correct location (.mokogitea/config.tf)" >> $GITHUB_STEP_SUMMARY else echo "ℹ️ No override configuration found" >> $GITHUB_STEP_SUMMARY fi From c537c63e9895cdf419c2a58aad2704526b9e6a1f Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 20:44:53 +0000 Subject: [PATCH 26/28] chore(ci): remove template-only sync workflows from root sync-on-merge.yml and workflow-sync-trigger.yml are template-only (gated if: Template-*), dead no-ops in this child repo, inherited at scaffold time. sync-on-merge.yml is also broken. The real sync lives in the templates' workflows/custom/. --- .mokogitea/workflows/sync-on-merge.yml | 32 -------- .../workflows/workflow-sync-trigger.yml | 82 ------------------- 2 files changed, 114 deletions(-) delete mode 100644 .mokogitea/workflows/sync-on-merge.yml delete mode 100644 .mokogitea/workflows/workflow-sync-trigger.yml diff --git a/.mokogitea/workflows/sync-on-merge.yml b/.mokogitea/workflows/sync-on-merge.yml deleted file mode 100644 index 3bf0d3b025..0000000000 --- a/.mokogitea/workflows/sync-on-merge.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Sync Workflows to Repos - -on: - push: - branches: - - main - paths: - - '.mokogitea/workflows/**' - -jobs: - sync: - runs-on: ubuntu-latest - if: ${{ startsWith(github.event.repository.name, 'Template-') }} - 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 }} diff --git a/.mokogitea/workflows/workflow-sync-trigger.yml b/.mokogitea/workflows/workflow-sync-trigger.yml deleted file mode 100644 index ccd9d584f1..0000000000 --- a/.mokogitea/workflows/workflow-sync-trigger.yml +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright (C) 2026 Moko Consulting -# -# SPDX-License-Identifier: GPL-3.0-or-later -# -# FILE INFORMATION -# DEFGROUP: MokoGitea.Workflow -# INGROUP: MokoCLI.Universal -# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic -# PATH: /.mokogitea/workflows/workflow-sync-trigger.yml -# VERSION: 01.01.00 -# BRIEF: Trigger workflow sync to live repos when a PR is merged to main - -name: "Universal: Workflow Sync Trigger" - -on: - workflow_dispatch: - pull_request: - types: [closed] - branches: - - main - -env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true - -jobs: - sync: - name: Sync workflows to live repos - runs-on: ubuntu-latest - if: >- - startsWith(github.event.repository.name, 'Template-') && - (github.event_name == 'workflow_dispatch' || - (github.event.pull_request.merged == true && - !contains(github.event.pull_request.title, '[skip sync]'))) - - steps: - - name: Determine platform from repo name - id: platform - run: | - REPO="${{ github.event.repository.name }}" - case "$REPO" in - Template-Joomla) PLATFORM="joomla" ;; - Template-Dolibarr) PLATFORM="dolibarr" ;; - Template-Go) PLATFORM="go" ;; - Template-MCP) PLATFORM="mcp" ;; - Template-Generic) PLATFORM="" ;; - *) PLATFORM="" ;; - esac - echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT" - echo "Platform: ${PLATFORM:-all}" - - - name: Clone MokoCLI - env: - MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} - run: | - 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: | - cd /tmp/mokocli - composer install --no-dev --no-interaction --quiet 2>/dev/null || true - - - name: Run workflow sync - env: - MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} - run: | - ARGS="--token ${MOKOGITEA_TOKEN}" - ARGS="${ARGS} --org ${{ vars.GITEA_ORG || github.repository_owner }}" - ARGS="${ARGS} --phase repos" - - PLATFORM="${{ steps.platform.outputs.platform }}" - if [ -n "$PLATFORM" ]; then - ARGS="${ARGS} --platform-filter ${PLATFORM}" - fi - - php /tmp/mokocli/cli/workflow_sync.php ${ARGS} From 385b96fda7504747f7c21def872b58fb122f4d8c Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 21:19:28 +0000 Subject: [PATCH 27/28] chore(ci): move repo-specific workflows to workflows/custom/ These are repo-specific (not platform-standard) and belong in custom/ so the workflow sync never distributes/clobbers them. They still run here (Gitea Actions executes custom/). Moved: deploy-rc.yml --- .mokogitea/workflows/{ => custom}/deploy-rc.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .mokogitea/workflows/{ => custom}/deploy-rc.yml (100%) diff --git a/.mokogitea/workflows/deploy-rc.yml b/.mokogitea/workflows/custom/deploy-rc.yml similarity index 100% rename from .mokogitea/workflows/deploy-rc.yml rename to .mokogitea/workflows/custom/deploy-rc.yml From 78b7c9e4afb718a5ad4f3810858a3ba619e1877b Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 13 Jul 2026 21:27:36 +0000 Subject: [PATCH 28/28] chore(ci): move deploy workflows out of custom/ to root Deploy workflows in go/npm repos live in the workflows root, not custom/ (mirrors npm repos' npm-publish.yml in root). The sync's curated set does not include deploy-*, so root placement is not clobbered. Moved: deploy-dev.yml, deploy-mokogitea.yml, deploy-rc.yml --- .mokogitea/workflows/{custom => }/deploy-dev.yml | 0 .mokogitea/workflows/{custom => }/deploy-mokogitea.yml | 0 .mokogitea/workflows/{custom => }/deploy-rc.yml | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename .mokogitea/workflows/{custom => }/deploy-dev.yml (100%) rename .mokogitea/workflows/{custom => }/deploy-mokogitea.yml (100%) rename .mokogitea/workflows/{custom => }/deploy-rc.yml (100%) diff --git a/.mokogitea/workflows/custom/deploy-dev.yml b/.mokogitea/workflows/deploy-dev.yml similarity index 100% rename from .mokogitea/workflows/custom/deploy-dev.yml rename to .mokogitea/workflows/deploy-dev.yml diff --git a/.mokogitea/workflows/custom/deploy-mokogitea.yml b/.mokogitea/workflows/deploy-mokogitea.yml similarity index 100% rename from .mokogitea/workflows/custom/deploy-mokogitea.yml rename to .mokogitea/workflows/deploy-mokogitea.yml diff --git a/.mokogitea/workflows/custom/deploy-rc.yml b/.mokogitea/workflows/deploy-rc.yml similarity index 100% rename from .mokogitea/workflows/custom/deploy-rc.yml rename to .mokogitea/workflows/deploy-rc.yml