feat: add development workflow improvements
- Add comprehensive workflow documentation (WORKFLOW_GUIDE.md) - Add quick start guide (QUICK_START.md) - Add caching to GitHub Actions workflows for faster CI/CD - Create Makefile with common development tasks - Add pre-commit hook script for local validation - Add VS Code tasks configuration - Add git hooks installation script - Update .gitignore to allow VS Code config files Co-authored-by: jmiller-moko <230051081+jmiller-moko@users.noreply.github.com>
This commit is contained in:
49
.github/workflows/joomla_testing.yml
vendored
49
.github/workflows/joomla_testing.yml
vendored
@@ -56,23 +56,46 @@ jobs:
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '18'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
|
||||
- name: Cache Joomla Downloads
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: /tmp/joomla-cache
|
||||
key: joomla-${{ matrix.joomla-version }}
|
||||
restore-keys: |
|
||||
joomla-${{ matrix.joomla-version }}
|
||||
|
||||
- name: Download Joomla ${{ matrix.joomla-version }}
|
||||
run: |
|
||||
mkdir -p /tmp/joomla
|
||||
cd /tmp/joomla
|
||||
mkdir -p /tmp/joomla-cache
|
||||
|
||||
# Download appropriate Joomla version
|
||||
# Define ZIP file based on version
|
||||
if [ "${{ matrix.joomla-version }}" = "4.4" ]; then
|
||||
wget -q https://downloads.joomla.org/cms/joomla4/4-4-9/Joomla_4-4-9-Stable-Full_Package.zip
|
||||
unzip -q Joomla_4-4-9-Stable-Full_Package.zip
|
||||
ZIP_FILE="Joomla_4-4-9-Stable-Full_Package.zip"
|
||||
ZIP_URL="https://downloads.joomla.org/cms/joomla4/4-4-9/${ZIP_FILE}"
|
||||
elif [ "${{ matrix.joomla-version }}" = "5.0" ]; then
|
||||
wget -q https://downloads.joomla.org/cms/joomla5/5-0-3/Joomla_5-0-3-Stable-Full_Package.zip
|
||||
unzip -q Joomla_5-0-3-Stable-Full_Package.zip
|
||||
ZIP_FILE="Joomla_5-0-3-Stable-Full_Package.zip"
|
||||
ZIP_URL="https://downloads.joomla.org/cms/joomla5/5-0-3/${ZIP_FILE}"
|
||||
else
|
||||
wget -q https://downloads.joomla.org/cms/joomla5/5-1-4/Joomla_5-1-4-Stable-Full_Package.zip
|
||||
unzip -q Joomla_5-1-4-Stable-Full_Package.zip
|
||||
ZIP_FILE="Joomla_5-1-4-Stable-Full_Package.zip"
|
||||
ZIP_URL="https://downloads.joomla.org/cms/joomla5/5-1-4/${ZIP_FILE}"
|
||||
fi
|
||||
|
||||
# Use cached ZIP if available, otherwise download
|
||||
if [ -f "/tmp/joomla-cache/${ZIP_FILE}" ]; then
|
||||
echo "Using cached Joomla package: ${ZIP_FILE}"
|
||||
cp "/tmp/joomla-cache/${ZIP_FILE}" "/tmp/joomla/"
|
||||
else
|
||||
echo "Downloading Joomla package: ${ZIP_FILE}"
|
||||
wget -q "${ZIP_URL}" -O "/tmp/joomla/${ZIP_FILE}"
|
||||
cp "/tmp/joomla/${ZIP_FILE}" "/tmp/joomla-cache/"
|
||||
fi
|
||||
|
||||
cd /tmp/joomla
|
||||
unzip -q "${ZIP_FILE}"
|
||||
|
||||
- name: Configure Joomla
|
||||
run: |
|
||||
@@ -211,6 +234,16 @@ jobs:
|
||||
coverage: xdebug
|
||||
tools: composer:v2
|
||||
|
||||
- name: Cache Composer packages
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.composer
|
||||
key: ${{ runner.os }}-composer-codeception-8.1-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-composer-codeception-8.1-
|
||||
${{ runner.os }}-composer-codeception-
|
||||
${{ runner.os }}-composer-
|
||||
|
||||
- name: Install Codeception
|
||||
run: |
|
||||
composer global require codeception/codeception
|
||||
|
||||
30
.github/workflows/php_quality.yml
vendored
30
.github/workflows/php_quality.yml
vendored
@@ -38,6 +38,16 @@ jobs:
|
||||
coverage: none
|
||||
tools: cs2pr
|
||||
|
||||
- name: Cache Composer packages
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.composer
|
||||
key: ${{ runner.os }}-composer-phpcs-${{ matrix.php-version }}-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-composer-phpcs-${{ matrix.php-version }}-
|
||||
${{ runner.os }}-composer-phpcs-
|
||||
${{ runner.os }}-composer-
|
||||
|
||||
- name: Install PHP_CodeSniffer
|
||||
run: |
|
||||
composer global require squizlabs/php_codesniffer
|
||||
@@ -82,6 +92,16 @@ jobs:
|
||||
extensions: mbstring, xml, ctype, json, zip
|
||||
coverage: none
|
||||
|
||||
- name: Cache Composer packages
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.composer
|
||||
key: ${{ runner.os }}-composer-phpstan-${{ matrix.php-version }}-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-composer-phpstan-${{ matrix.php-version }}-
|
||||
${{ runner.os }}-composer-phpstan-
|
||||
${{ runner.os }}-composer-
|
||||
|
||||
- name: Install PHPStan
|
||||
run: |
|
||||
composer global require phpstan/phpstan
|
||||
@@ -119,6 +139,16 @@ jobs:
|
||||
extensions: mbstring, xml, ctype, json, zip
|
||||
coverage: none
|
||||
|
||||
- name: Cache Composer packages
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.composer
|
||||
key: ${{ runner.os }}-composer-phpcompat-8.3-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-composer-phpcompat-8.3-
|
||||
${{ runner.os }}-composer-phpcompat-
|
||||
${{ runner.os }}-composer-
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
composer global require squizlabs/php_codesniffer
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -33,7 +33,11 @@ System Volume Information/
|
||||
*.lnk
|
||||
Icon?
|
||||
.idea/
|
||||
.vscode/
|
||||
# .vscode/ - Allow specific VS Code config files
|
||||
.vscode/*
|
||||
!.vscode/tasks.json
|
||||
!.vscode/settings.json.example
|
||||
!.vscode/extensions.json
|
||||
*.code-workspace
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
|
||||
171
.vscode/tasks.json
vendored
Normal file
171
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Validate All",
|
||||
"type": "shell",
|
||||
"command": "./scripts/run/validate_all.sh",
|
||||
"group": {
|
||||
"kind": "test",
|
||||
"isDefault": true
|
||||
},
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "new"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Validate Required",
|
||||
"type": "shell",
|
||||
"command": "make validate-required",
|
||||
"group": "test",
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "new"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Run Tests",
|
||||
"type": "shell",
|
||||
"command": "codecept run",
|
||||
"group": "test",
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "new"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "PHP CodeSniffer",
|
||||
"type": "shell",
|
||||
"command": "phpcs --standard=phpcs.xml src/",
|
||||
"group": "test",
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "shared"
|
||||
},
|
||||
"problemMatcher": {
|
||||
"owner": "php",
|
||||
"fileLocation": "relative",
|
||||
"pattern": {
|
||||
"regexp": "^(.+):(\\d+):(\\d+):\\s+(error|warning)\\s+-\\s+(.+)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"column": 3,
|
||||
"severity": 4,
|
||||
"message": 5
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "PHP CodeSniffer - Auto Fix",
|
||||
"type": "shell",
|
||||
"command": "phpcbf --standard=phpcs.xml src/",
|
||||
"group": "none",
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "shared"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "PHPStan",
|
||||
"type": "shell",
|
||||
"command": "phpstan analyse --configuration=phpstan.neon",
|
||||
"group": "test",
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "shared"
|
||||
},
|
||||
"problemMatcher": {
|
||||
"owner": "php",
|
||||
"fileLocation": "relative",
|
||||
"pattern": {
|
||||
"regexp": "^(.+):(\\d+):\\s+(.+)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"message": 3
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Create Package",
|
||||
"type": "shell",
|
||||
"command": "./scripts/release/package_extension.sh dist",
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "new"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Smoke Test",
|
||||
"type": "shell",
|
||||
"command": "./scripts/run/smoke_test.sh",
|
||||
"group": "test",
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "new"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Script Health Check",
|
||||
"type": "shell",
|
||||
"command": "./scripts/run/script_health.sh",
|
||||
"group": "test",
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "new"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Check Code Quality",
|
||||
"type": "shell",
|
||||
"command": "make quality",
|
||||
"group": "test",
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "new"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Fix Permissions",
|
||||
"type": "shell",
|
||||
"command": "make fix-permissions",
|
||||
"group": "none",
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "shared"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Clean",
|
||||
"type": "shell",
|
||||
"command": "make clean",
|
||||
"group": "none",
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "shared"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Install Git Hooks",
|
||||
"type": "shell",
|
||||
"command": "./scripts/git/install-hooks.sh",
|
||||
"group": "none",
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "new"
|
||||
},
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
}
|
||||
193
Makefile
Normal file
193
Makefile
Normal file
@@ -0,0 +1,193 @@
|
||||
# Makefile for Moko Cassiopeia Development
|
||||
# Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
.PHONY: help install validate test quality package clean dev-setup
|
||||
|
||||
# Default target
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
# Version detection
|
||||
VERSION := $(shell grep -oP '<version>\K[^<]+' src/templates/templateDetails.xml 2>/dev/null || echo "unknown")
|
||||
|
||||
## help: Show this help message
|
||||
help:
|
||||
@echo "Moko Cassiopeia Development Makefile"
|
||||
@echo ""
|
||||
@echo "Version: $(VERSION)"
|
||||
@echo ""
|
||||
@echo "Available targets:"
|
||||
@sed -n 's/^##//p' $(MAKEFILE_LIST) | column -t -s ':' | sed -e 's/^/ /'
|
||||
|
||||
## install: Install development dependencies
|
||||
install:
|
||||
@echo "Installing development dependencies..."
|
||||
@command -v composer >/dev/null 2>&1 || { echo "Error: composer not found. Please install composer first."; exit 1; }
|
||||
composer global require squizlabs/php_codesniffer
|
||||
composer global require phpstan/phpstan
|
||||
composer global require phpcompatibility/php-compatibility
|
||||
composer global require codeception/codeception
|
||||
phpcs --config-set installed_paths ~/.composer/vendor/phpcompatibility/php-compatibility
|
||||
@echo "✓ Dependencies installed"
|
||||
|
||||
## validate: Run all validation scripts
|
||||
validate:
|
||||
@echo "Running validation scripts..."
|
||||
@./scripts/run/validate_all.sh
|
||||
|
||||
## validate-required: Run only required validation scripts
|
||||
validate-required:
|
||||
@echo "Running required validations..."
|
||||
@./scripts/validate/manifest.sh
|
||||
@./scripts/validate/xml_wellformed.sh
|
||||
@./scripts/validate/workflows.sh
|
||||
@echo "✓ Required validations passed"
|
||||
|
||||
## test: Run all tests
|
||||
test:
|
||||
@echo "Running tests..."
|
||||
@command -v codecept >/dev/null 2>&1 || { echo "Error: codecept not found. Run 'make install' first."; exit 1; }
|
||||
codecept run
|
||||
|
||||
## test-unit: Run unit tests only
|
||||
test-unit:
|
||||
@echo "Running unit tests..."
|
||||
@command -v codecept >/dev/null 2>&1 || { echo "Error: codecept not found. Run 'make install' first."; exit 1; }
|
||||
codecept run unit
|
||||
|
||||
## test-acceptance: Run acceptance tests only
|
||||
test-acceptance:
|
||||
@echo "Running acceptance tests..."
|
||||
@command -v codecept >/dev/null 2>&1 || { echo "Error: codecept not found. Run 'make install' first."; exit 1; }
|
||||
codecept run acceptance
|
||||
|
||||
## quality: Run code quality checks
|
||||
quality:
|
||||
@echo "Running code quality checks..."
|
||||
@$(MAKE) phpcs
|
||||
@$(MAKE) phpstan
|
||||
@$(MAKE) phpcompat
|
||||
|
||||
## phpcs: Run PHP_CodeSniffer
|
||||
phpcs:
|
||||
@echo "Running PHP_CodeSniffer..."
|
||||
@command -v phpcs >/dev/null 2>&1 || { echo "Error: phpcs not found. Run 'make install' first."; exit 1; }
|
||||
phpcs --standard=phpcs.xml src/
|
||||
|
||||
## phpcs-fix: Auto-fix PHPCS violations
|
||||
phpcs-fix:
|
||||
@echo "Auto-fixing PHPCS violations..."
|
||||
@command -v phpcbf >/dev/null 2>&1 || { echo "Error: phpcbf not found. Run 'make install' first."; exit 1; }
|
||||
phpcbf --standard=phpcs.xml src/
|
||||
|
||||
## phpstan: Run PHPStan static analysis
|
||||
phpstan:
|
||||
@echo "Running PHPStan..."
|
||||
@command -v phpstan >/dev/null 2>&1 || { echo "Error: phpstan not found. Run 'make install' first."; exit 1; }
|
||||
phpstan analyse --configuration=phpstan.neon
|
||||
|
||||
## phpcompat: Check PHP 8.0+ compatibility
|
||||
phpcompat:
|
||||
@echo "Checking PHP 8.0+ compatibility..."
|
||||
@command -v phpcs >/dev/null 2>&1 || { echo "Error: phpcs not found. Run 'make install' first."; exit 1; }
|
||||
phpcs --standard=PHPCompatibility --runtime-set testVersion 8.0- src/
|
||||
|
||||
## package: Create distribution package
|
||||
package:
|
||||
@echo "Creating distribution package..."
|
||||
@./scripts/release/package_extension.sh dist $(VERSION)
|
||||
@echo "✓ Package created: dist/moko-cassiopeia-$(VERSION)-*.zip"
|
||||
|
||||
## smoke-test: Run smoke tests
|
||||
smoke-test:
|
||||
@echo "Running smoke tests..."
|
||||
@./scripts/run/smoke_test.sh
|
||||
|
||||
## script-health: Check script health
|
||||
script-health:
|
||||
@echo "Checking script health..."
|
||||
@./scripts/run/script_health.sh
|
||||
|
||||
## version-check: Display current version information
|
||||
version-check:
|
||||
@echo "Version Information:"
|
||||
@echo " Manifest: $(VERSION)"
|
||||
@echo " Latest CHANGELOG entry:"
|
||||
@grep -m 1 "^## \[" CHANGELOG.md || echo " (not found)"
|
||||
|
||||
## fix-permissions: Fix script executable permissions
|
||||
fix-permissions:
|
||||
@echo "Fixing script permissions..."
|
||||
@find scripts -type f -name "*.sh" -exec chmod +x {} \;
|
||||
@echo "✓ Permissions fixed"
|
||||
|
||||
## clean: Remove generated files and caches
|
||||
clean:
|
||||
@echo "Cleaning generated files..."
|
||||
@rm -rf dist/
|
||||
@rm -rf tests/_output/
|
||||
@rm -rf .phpunit.cache/
|
||||
@find . -type f -name "*.log" -delete
|
||||
@find . -type f -name ".DS_Store" -delete
|
||||
@echo "✓ Cleaned"
|
||||
|
||||
## dev-setup: Complete development environment setup
|
||||
dev-setup:
|
||||
@echo "Setting up development environment..."
|
||||
@$(MAKE) install
|
||||
@$(MAKE) fix-permissions
|
||||
@echo ""
|
||||
@echo "✓ Development environment ready!"
|
||||
@echo ""
|
||||
@echo "Quick start:"
|
||||
@echo " make validate - Run all validations"
|
||||
@echo " make test - Run tests"
|
||||
@echo " make quality - Check code quality"
|
||||
@echo " make package - Create distribution package"
|
||||
|
||||
## format: Format code (PHPCS auto-fix)
|
||||
format: phpcs-fix
|
||||
|
||||
## check: Quick check (required validations + quality)
|
||||
check:
|
||||
@echo "Running quick checks..."
|
||||
@$(MAKE) validate-required
|
||||
@$(MAKE) quality
|
||||
@echo "✓ All checks passed"
|
||||
|
||||
## all: Run everything (validate, test, quality, package)
|
||||
all:
|
||||
@echo "Running complete build pipeline..."
|
||||
@$(MAKE) validate
|
||||
@$(MAKE) test
|
||||
@$(MAKE) quality
|
||||
@$(MAKE) package
|
||||
@echo "✓ Complete pipeline successful"
|
||||
|
||||
## watch: Watch for changes and run validations (requires entr)
|
||||
watch:
|
||||
@echo "Watching for changes... (Ctrl+C to stop)"
|
||||
@command -v entr >/dev/null 2>&1 || { echo "Error: entr not found. Install with: apt-get install entr"; exit 1; }
|
||||
@find src -type f | entr -c make validate-required
|
||||
|
||||
## list-scripts: List all available scripts
|
||||
list-scripts:
|
||||
@echo "Available validation scripts:"
|
||||
@find scripts/validate -type f -name "*.sh" -exec basename {} \; | sort
|
||||
@echo ""
|
||||
@echo "Available fix scripts:"
|
||||
@find scripts/fix -type f -name "*.sh" -exec basename {} \; | sort
|
||||
@echo ""
|
||||
@echo "Available run scripts:"
|
||||
@find scripts/run -type f -name "*.sh" -exec basename {} \; | sort
|
||||
|
||||
## docs: Open documentation
|
||||
docs:
|
||||
@echo "Documentation files:"
|
||||
@echo " README.md - Project overview"
|
||||
@echo " docs/JOOMLA_DEVELOPMENT.md - Development guide"
|
||||
@echo " docs/WORKFLOW_GUIDE.md - Workflow reference"
|
||||
@echo " scripts/README.md - Scripts documentation"
|
||||
@echo " CHANGELOG.md - Version history"
|
||||
@echo " CONTRIBUTING.md - Contribution guide"
|
||||
352
docs/QUICK_START.md
Normal file
352
docs/QUICK_START.md
Normal file
@@ -0,0 +1,352 @@
|
||||
# Quick Start Guide - Moko Cassiopeia Development
|
||||
|
||||
Get up and running with Moko Cassiopeia development in minutes.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you begin, ensure you have:
|
||||
|
||||
- **Git** - For version control
|
||||
- **PHP 8.0+** - Required runtime
|
||||
- **Composer** - PHP dependency manager
|
||||
- **Make** (optional) - For convenient commands
|
||||
- **Code Editor** - VS Code recommended (tasks pre-configured)
|
||||
|
||||
## 5-Minute Setup
|
||||
|
||||
### 1. Clone the Repository
|
||||
|
||||
```bash
|
||||
git clone https://github.com/mokoconsulting-tech/moko-cassiopeia.git
|
||||
cd moko-cassiopeia
|
||||
```
|
||||
|
||||
### 2. Install Development Dependencies
|
||||
|
||||
```bash
|
||||
# Using Make (recommended)
|
||||
make dev-setup
|
||||
|
||||
# Or manually
|
||||
composer global require squizlabs/php_codesniffer
|
||||
composer global require phpstan/phpstan
|
||||
composer global require phpcompatibility/php-compatibility
|
||||
composer global require codeception/codeception
|
||||
```
|
||||
|
||||
### 3. Install Git Hooks (Optional but Recommended)
|
||||
|
||||
```bash
|
||||
./scripts/git/install-hooks.sh
|
||||
```
|
||||
|
||||
### 4. Validate Everything Works
|
||||
|
||||
```bash
|
||||
# Quick validation
|
||||
make validate-required
|
||||
|
||||
# Or comprehensive validation
|
||||
make validate
|
||||
```
|
||||
|
||||
## Common Tasks
|
||||
|
||||
### Development Workflow
|
||||
|
||||
```bash
|
||||
# 1. Make your changes
|
||||
vim src/templates/index.php
|
||||
|
||||
# 2. Validate locally
|
||||
make validate-required
|
||||
|
||||
# 3. Check code quality
|
||||
make quality
|
||||
|
||||
# 4. Commit
|
||||
git add -A
|
||||
git commit -m "feat: add new feature"
|
||||
# (pre-commit hook runs automatically)
|
||||
|
||||
# 5. Push
|
||||
git push origin your-branch
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
make test
|
||||
|
||||
# Run unit tests only
|
||||
make test-unit
|
||||
|
||||
# Run acceptance tests only
|
||||
make test-acceptance
|
||||
```
|
||||
|
||||
### Code Quality
|
||||
|
||||
```bash
|
||||
# Check everything
|
||||
make quality
|
||||
|
||||
# PHP CodeSniffer only
|
||||
make phpcs
|
||||
|
||||
# Auto-fix PHPCS issues
|
||||
make phpcs-fix
|
||||
|
||||
# PHPStan only
|
||||
make phpstan
|
||||
|
||||
# PHP compatibility check
|
||||
make phpcompat
|
||||
```
|
||||
|
||||
### Creating a Release Package
|
||||
|
||||
```bash
|
||||
# Package with auto-detected version
|
||||
make package
|
||||
|
||||
# Or specify directory and version
|
||||
./scripts/release/package_extension.sh dist 03.05.00
|
||||
|
||||
# Check package contents
|
||||
ls -lh dist/
|
||||
unzip -l dist/moko-cassiopeia-*.zip
|
||||
```
|
||||
|
||||
## VS Code Integration
|
||||
|
||||
If using VS Code, press `Ctrl+Shift+P` (or `Cmd+Shift+P` on Mac) and type "Run Task" to see available tasks:
|
||||
|
||||
- **Validate All** - Run all validation scripts (default test task)
|
||||
- **Validate Required** - Run only required validations
|
||||
- **PHP CodeSniffer** - Check code style
|
||||
- **PHP CodeSniffer - Auto Fix** - Fix code style issues
|
||||
- **PHPStan** - Static analysis
|
||||
- **Run Tests** - Execute all tests
|
||||
- **Create Package** - Build distribution ZIP
|
||||
- **Install Git Hooks** - Set up pre-commit hooks
|
||||
|
||||
## Available Make Commands
|
||||
|
||||
Run `make help` to see all available commands:
|
||||
|
||||
```bash
|
||||
make help # Show all commands
|
||||
make dev-setup # Complete environment setup
|
||||
make validate # Run all validations
|
||||
make test # Run all tests
|
||||
make quality # Check code quality
|
||||
make package # Create distribution package
|
||||
make clean # Remove generated files
|
||||
make check # Quick check (validate + quality)
|
||||
make all # Complete build pipeline
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
moko-cassiopeia/
|
||||
├── src/ # Joomla template source
|
||||
│ ├── templates/ # Template files
|
||||
│ ├── media/ # Assets (CSS, JS, images)
|
||||
│ ├── language/ # Language files
|
||||
│ └── administrator/ # Admin files
|
||||
├── scripts/ # Automation scripts
|
||||
│ ├── validate/ # Validation scripts
|
||||
│ ├── fix/ # Fix/update scripts
|
||||
│ ├── release/ # Release scripts
|
||||
│ ├── run/ # Execution scripts
|
||||
│ ├── git/ # Git hooks
|
||||
│ └── lib/ # Shared libraries
|
||||
├── tests/ # Test suites
|
||||
├── docs/ # Documentation
|
||||
├── .github/workflows/ # CI/CD workflows
|
||||
├── Makefile # Make commands
|
||||
└── README.md # Project overview
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
### Learning the Workflow
|
||||
|
||||
1. **Read the Workflow Guide**: [docs/WORKFLOW_GUIDE.md](./WORKFLOW_GUIDE.md)
|
||||
2. **Review Joomla Development**: [docs/JOOMLA_DEVELOPMENT.md](./JOOMLA_DEVELOPMENT.md)
|
||||
3. **Check Scripts Documentation**: [scripts/README.md](../scripts/README.md)
|
||||
|
||||
### Creating Your First Feature
|
||||
|
||||
1. **Create a version branch** via GitHub Actions:
|
||||
- Go to Actions → Create version branch
|
||||
- Enter version (e.g., 03.06.00)
|
||||
- Select branch prefix: `dev/`
|
||||
- Run workflow
|
||||
|
||||
2. **Checkout the branch**:
|
||||
```bash
|
||||
git fetch origin
|
||||
git checkout dev/03.06.00
|
||||
```
|
||||
|
||||
3. **Make changes and test**:
|
||||
```bash
|
||||
# Edit files
|
||||
vim src/templates/index.php
|
||||
|
||||
# Validate
|
||||
make validate-required
|
||||
|
||||
# Check quality
|
||||
make quality
|
||||
```
|
||||
|
||||
4. **Commit and push**:
|
||||
```bash
|
||||
git add -A
|
||||
git commit -m "feat: your feature description"
|
||||
git push origin dev/03.06.00
|
||||
```
|
||||
|
||||
5. **Watch CI**: Check GitHub Actions for automated testing
|
||||
|
||||
### Understanding the Release Process
|
||||
|
||||
```
|
||||
Development → RC → Stable → Production
|
||||
(dev/) (rc/) (version/) (main)
|
||||
```
|
||||
|
||||
1. **dev/X.Y.Z** - Active development
|
||||
2. **rc/X.Y.Z** - Release candidate testing
|
||||
3. **version/X.Y.Z** - Stable release
|
||||
4. **main** - Production (auto-merged from version/)
|
||||
|
||||
Use the Release Pipeline workflow to promote between stages.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Scripts Not Executable
|
||||
|
||||
```bash
|
||||
make fix-permissions
|
||||
# Or manually:
|
||||
chmod +x scripts/**/*.sh
|
||||
```
|
||||
|
||||
### PHPStan/PHPCS Not Found
|
||||
|
||||
```bash
|
||||
make install
|
||||
# Or manually:
|
||||
composer global require squizlabs/php_codesniffer phpstan/phpstan
|
||||
```
|
||||
|
||||
### Pre-commit Hook Fails
|
||||
|
||||
```bash
|
||||
# Run manually to see details
|
||||
./scripts/git/pre-commit.sh
|
||||
|
||||
# Quick mode (skip some checks)
|
||||
./scripts/git/pre-commit.sh --quick
|
||||
|
||||
# Skip quality checks
|
||||
./scripts/git/pre-commit.sh --skip-quality
|
||||
|
||||
# Bypass hook (not recommended)
|
||||
git commit --no-verify
|
||||
```
|
||||
|
||||
### CI Workflow Fails
|
||||
|
||||
1. Check the workflow logs in GitHub Actions
|
||||
2. Run the same checks locally:
|
||||
```bash
|
||||
./scripts/validate/manifest.sh
|
||||
./scripts/validate/php_syntax.sh
|
||||
make quality
|
||||
```
|
||||
|
||||
### Need Help?
|
||||
|
||||
- **Documentation**: Check [docs/](../docs/) directory
|
||||
- **Issues**: Open an issue on GitHub
|
||||
- **Contributing**: See [CONTRIBUTING.md](../CONTRIBUTING.md)
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Before Committing
|
||||
|
||||
```bash
|
||||
# Always validate first
|
||||
make validate-required
|
||||
|
||||
# Check quality for PHP changes
|
||||
make quality
|
||||
|
||||
# Run tests if you changed functionality
|
||||
make test
|
||||
```
|
||||
|
||||
### Code Style
|
||||
|
||||
- Follow PSR-12 standards
|
||||
- Use `make phpcs-fix` to auto-fix issues
|
||||
- Add SPDX license headers to new files
|
||||
- Keep functions small and focused
|
||||
|
||||
### Documentation
|
||||
|
||||
- Update docs when changing workflows
|
||||
- Add comments for complex logic
|
||||
- Update CHANGELOG.md with changes
|
||||
- Keep README.md current
|
||||
|
||||
### Version Management
|
||||
|
||||
- Use semantic versioning: Major.Minor.Patch (03.05.00)
|
||||
- Update CHANGELOG.md with all changes
|
||||
- Follow the version hierarchy: dev → rc → version → main
|
||||
- Never skip stages in the release process
|
||||
|
||||
## Useful Resources
|
||||
|
||||
- [Joomla Documentation](https://docs.joomla.org/)
|
||||
- [PSR-12 Coding Standard](https://www.php-fig.org/psr/psr-12/)
|
||||
- [Semantic Versioning](https://semver.org/)
|
||||
- [Conventional Commits](https://www.conventionalcommits.org/)
|
||||
|
||||
## Quick Reference Card
|
||||
|
||||
```bash
|
||||
# Setup
|
||||
make dev-setup # Initial setup
|
||||
./scripts/git/install-hooks.sh # Install hooks
|
||||
|
||||
# Development
|
||||
make validate-required # Quick validation
|
||||
make quality # Code quality
|
||||
make test # Run tests
|
||||
|
||||
# Building
|
||||
make package # Create ZIP
|
||||
|
||||
# Maintenance
|
||||
make clean # Clean generated files
|
||||
make fix-permissions # Fix script permissions
|
||||
|
||||
# Help
|
||||
make help # Show all commands
|
||||
./scripts/run/validate_all.sh --help # Script help
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Document Version:** 1.0.0
|
||||
**Last Updated:** 2026-01-04
|
||||
**Get Started:** Run `make dev-setup` now!
|
||||
472
docs/WORKFLOW_GUIDE.md
Normal file
472
docs/WORKFLOW_GUIDE.md
Normal file
@@ -0,0 +1,472 @@
|
||||
# Workflow Guide - Moko Cassiopeia
|
||||
|
||||
Quick reference guide for GitHub Actions workflows and common development tasks.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Workflow Quick Reference](#workflow-quick-reference)
|
||||
- [Common Development Tasks](#common-development-tasks)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
- [Best Practices](#best-practices)
|
||||
|
||||
## Overview
|
||||
|
||||
This repository uses GitHub Actions for continuous integration, testing, quality checks, and deployment. All workflows are located in `.github/workflows/`.
|
||||
|
||||
### Workflow Execution Model
|
||||
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ Code Changes │
|
||||
└────────┬────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ CI Pipeline │ ← Validation, Testing, Quality
|
||||
└────────┬────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ Version Branch │ ← Create dev/X.Y.Z branch
|
||||
└────────┬────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ Release Pipeline│ ← dev → rc → version → main
|
||||
└────────┬────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ Distribution │ ← ZIP package + GitHub Release
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
## Workflow Quick Reference
|
||||
|
||||
### Continuous Integration (ci.yml)
|
||||
|
||||
**Trigger:** Automatic on push/PR to main, dev/*, rc/*, version/* branches
|
||||
|
||||
**Purpose:** Validates code quality and repository structure
|
||||
|
||||
**What it does:**
|
||||
- ✅ Validates Joomla manifest XML
|
||||
- ✅ Checks XML well-formedness
|
||||
- ✅ Validates GitHub Actions workflows
|
||||
- ✅ Runs PHP syntax checks
|
||||
- ✅ Checks for secrets in code
|
||||
- ✅ Validates license headers
|
||||
- ✅ Verifies version alignment
|
||||
|
||||
**When to check:** After every commit
|
||||
|
||||
**How to view results:**
|
||||
```bash
|
||||
# Via GitHub CLI
|
||||
gh run list --workflow=ci.yml --limit 5
|
||||
gh run view <run-id> --log
|
||||
```
|
||||
|
||||
### PHP Quality Checks (php_quality.yml)
|
||||
|
||||
**Trigger:** Automatic on push/PR to main, dev/*, rc/*, version/* branches
|
||||
|
||||
**Purpose:** Ensures PHP code quality and compatibility
|
||||
|
||||
**What it does:**
|
||||
- 🔍 PHPStan static analysis (level 5)
|
||||
- 📏 PHP_CodeSniffer with PSR-12 standards
|
||||
- ✔️ PHP 8.0+ compatibility checks
|
||||
|
||||
**Matrix:** PHP 8.0, 8.1, 8.2, 8.3
|
||||
|
||||
**When to check:** Before committing PHP changes
|
||||
|
||||
**How to run locally:**
|
||||
```bash
|
||||
# Install tools
|
||||
composer global require squizlabs/php_codesniffer phpstan/phpstan
|
||||
|
||||
# Run checks
|
||||
phpcs --standard=phpcs.xml src/
|
||||
phpstan analyse --configuration=phpstan.neon
|
||||
```
|
||||
|
||||
### Joomla Testing (joomla_testing.yml)
|
||||
|
||||
**Trigger:** Automatic on push/PR to main, dev/*, rc/* branches
|
||||
|
||||
**Purpose:** Tests template compatibility with Joomla versions
|
||||
|
||||
**What it does:**
|
||||
- 📦 Downloads and installs Joomla (4.4, 5.0, 5.1)
|
||||
- 🔧 Installs template into Joomla
|
||||
- ✅ Validates template installation
|
||||
- 🧪 Runs Codeception tests
|
||||
|
||||
**Matrix:** Joomla 4.4/5.0/5.1 × PHP 8.0/8.1/8.2/8.3
|
||||
|
||||
**When to check:** Before releasing new versions
|
||||
|
||||
**How to test locally:**
|
||||
```bash
|
||||
# See docs/JOOMLA_DEVELOPMENT.md for local testing setup
|
||||
codecept run
|
||||
```
|
||||
|
||||
### Version Branch Creation (version_branch.yml)
|
||||
|
||||
**Trigger:** Manual workflow dispatch
|
||||
|
||||
**Purpose:** Creates a new version branch and bumps version numbers
|
||||
|
||||
**What it does:**
|
||||
- 🏷️ Creates dev/*, rc/*, or version/* branch
|
||||
- 📝 Updates version in all files
|
||||
- 📅 Updates manifest dates
|
||||
- 📋 Moves CHANGELOG unreleased to version
|
||||
- ✅ Validates version hierarchy
|
||||
|
||||
**When to use:** Starting work on a new version
|
||||
|
||||
**How to run:**
|
||||
1. Go to Actions → Create version branch
|
||||
2. Click "Run workflow"
|
||||
3. Enter version (e.g., 03.05.00)
|
||||
4. Select branch prefix (dev/, rc/, or version/)
|
||||
5. Click "Run workflow"
|
||||
|
||||
**Example:**
|
||||
```yaml
|
||||
new_version: 03.06.00
|
||||
branch_prefix: dev/
|
||||
version_text: beta
|
||||
```
|
||||
|
||||
### Release Pipeline (release_pipeline.yml)
|
||||
|
||||
**Trigger:** Manual workflow dispatch or release event
|
||||
|
||||
**Purpose:** Promotes branches through release stages and creates distributions
|
||||
|
||||
**What it does:**
|
||||
- 🔄 Promotes branches: dev → rc → version → main
|
||||
- 📅 Normalizes dates in manifest and CHANGELOG
|
||||
- 📦 Builds distributable ZIP package
|
||||
- 🚀 Uploads to SFTP server
|
||||
- 🏷️ Creates Git tag
|
||||
- 📋 Creates GitHub Release
|
||||
- 🔒 Attests build provenance
|
||||
|
||||
**When to use:** Promoting a version through release stages
|
||||
|
||||
**How to run:**
|
||||
1. Go to Actions → Release Pipeline
|
||||
2. Click "Run workflow"
|
||||
3. Select classification (auto/rc/stable)
|
||||
4. Click "Run workflow"
|
||||
|
||||
**Release flow:**
|
||||
```
|
||||
dev/X.Y.Z → rc/X.Y.Z → version/X.Y.Z → main
|
||||
(dev) (RC) (stable) (production)
|
||||
```
|
||||
|
||||
### Deploy to Staging (deploy_staging.yml)
|
||||
|
||||
**Trigger:** Manual workflow dispatch
|
||||
|
||||
**Purpose:** Deploys template to staging/development environments
|
||||
|
||||
**What it does:**
|
||||
- ✅ Validates deployment prerequisites
|
||||
- 📦 Builds deployment package
|
||||
- 🚀 Uploads via SFTP to environment
|
||||
- 📝 Creates deployment summary
|
||||
|
||||
**When to use:** Testing in staging before production release
|
||||
|
||||
**How to run:**
|
||||
1. Go to Actions → Deploy to Staging
|
||||
2. Click "Run workflow"
|
||||
3. Select environment (staging/development/preview)
|
||||
4. Optionally specify version
|
||||
5. Click "Run workflow"
|
||||
|
||||
**Required secrets:**
|
||||
- `STAGING_HOST` - SFTP hostname
|
||||
- `STAGING_USER` - SFTP username
|
||||
- `STAGING_KEY` - SSH private key (or `STAGING_PASSWORD`)
|
||||
- `STAGING_PATH` - Remote deployment path
|
||||
|
||||
### Repository Health (repo_health.yml)
|
||||
|
||||
**Trigger:** Manual workflow dispatch (admin only)
|
||||
|
||||
**Purpose:** Comprehensive repository health and configuration checks
|
||||
|
||||
**What it does:**
|
||||
- 🔐 Validates release configuration
|
||||
- 🌐 Tests SFTP connectivity
|
||||
- 📂 Checks scripts governance
|
||||
- 📄 Validates required artifacts
|
||||
- 🔍 Extended checks (SPDX, ShellCheck, etc.)
|
||||
|
||||
**When to use:** Before major releases or when debugging deployment issues
|
||||
|
||||
**How to run:**
|
||||
1. Go to Actions → Repo Health
|
||||
2. Click "Run workflow"
|
||||
3. Select profile (all/release/scripts/repo)
|
||||
4. Click "Run workflow"
|
||||
|
||||
**Profiles:**
|
||||
- `all` - Run all checks
|
||||
- `release` - Release configuration and SFTP only
|
||||
- `scripts` - Scripts governance only
|
||||
- `repo` - Repository health only
|
||||
|
||||
## Common Development Tasks
|
||||
|
||||
### Starting a New Feature
|
||||
|
||||
```bash
|
||||
# 1. Create a new version branch via GitHub Actions
|
||||
# Actions → Create version branch → dev/X.Y.Z
|
||||
|
||||
# 2. Clone and checkout the new branch
|
||||
git fetch origin
|
||||
git checkout dev/X.Y.Z
|
||||
|
||||
# 3. Make your changes
|
||||
vim src/templates/index.php
|
||||
|
||||
# 4. Validate locally
|
||||
./scripts/validate/php_syntax.sh
|
||||
./scripts/validate/manifest.sh
|
||||
|
||||
# 5. Commit and push
|
||||
git add -A
|
||||
git commit -m "feat: add new feature"
|
||||
git push origin dev/X.Y.Z
|
||||
```
|
||||
|
||||
### Running All Validations Locally
|
||||
|
||||
```bash
|
||||
# Run comprehensive validation suite
|
||||
./scripts/run/validate_all.sh
|
||||
|
||||
# Run with verbose output
|
||||
./scripts/run/validate_all.sh -v
|
||||
|
||||
# Run smoke tests
|
||||
./scripts/run/smoke_test.sh
|
||||
```
|
||||
|
||||
### Creating a Release Package
|
||||
|
||||
```bash
|
||||
# Package with auto-detected version
|
||||
./scripts/release/package_extension.sh
|
||||
|
||||
# Package with specific version
|
||||
./scripts/release/package_extension.sh dist 03.05.00
|
||||
|
||||
# Verify package contents
|
||||
unzip -l dist/moko-cassiopeia-*.zip
|
||||
```
|
||||
|
||||
### Updating Version Numbers
|
||||
|
||||
```bash
|
||||
# Via GitHub Actions (recommended)
|
||||
# Actions → Create version branch
|
||||
|
||||
# Or manually with scripts
|
||||
./scripts/fix/versions.sh 03.05.00
|
||||
```
|
||||
|
||||
### Updating CHANGELOG
|
||||
|
||||
```bash
|
||||
# Add new version entry
|
||||
./scripts/release/update_changelog.sh 03.05.00
|
||||
|
||||
# Update release dates
|
||||
./scripts/release/update_dates.sh 2025-01-15 03.05.00
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### CI Failures
|
||||
|
||||
#### PHP Syntax Errors
|
||||
|
||||
```bash
|
||||
# Check specific file
|
||||
php -l src/templates/index.php
|
||||
|
||||
# Run validation script
|
||||
./scripts/validate/php_syntax.sh
|
||||
```
|
||||
|
||||
#### Manifest Validation Failed
|
||||
|
||||
```bash
|
||||
# Validate manifest XML
|
||||
./scripts/validate/manifest.sh
|
||||
|
||||
# Check XML well-formedness
|
||||
./scripts/validate/xml_wellformed.sh
|
||||
```
|
||||
|
||||
#### Version Alignment Issues
|
||||
|
||||
```bash
|
||||
# Check version in manifest matches CHANGELOG
|
||||
./scripts/validate/version_alignment.sh
|
||||
|
||||
# Fix versions
|
||||
./scripts/fix/versions.sh 03.05.00
|
||||
```
|
||||
|
||||
### Workflow Failures
|
||||
|
||||
#### "Permission denied" on scripts
|
||||
|
||||
```bash
|
||||
# Fix script permissions
|
||||
chmod +x scripts/**/*.sh
|
||||
```
|
||||
|
||||
#### "Branch already exists"
|
||||
|
||||
```bash
|
||||
# Check existing branches
|
||||
git branch -r | grep dev/
|
||||
|
||||
# Delete remote branch if needed (carefully!)
|
||||
git push origin --delete dev/03.05.00
|
||||
```
|
||||
|
||||
#### "Missing required secrets"
|
||||
|
||||
Go to repository Settings → Secrets and variables → Actions, and add:
|
||||
- `FTP_HOST`
|
||||
- `FTP_USER`
|
||||
- `FTP_KEY` or `FTP_PASSWORD`
|
||||
- `FTP_PATH`
|
||||
|
||||
#### SFTP Connection Failed
|
||||
|
||||
1. Verify credentials in repo_health workflow:
|
||||
- Actions → Repo Health → profile: release
|
||||
|
||||
2. Check SSH key format (OpenSSH, not PuTTY PPK)
|
||||
|
||||
3. Verify server allows connections from GitHub IPs
|
||||
|
||||
### Quality Check Failures
|
||||
|
||||
#### PHPStan Errors
|
||||
|
||||
```bash
|
||||
# Run locally to see full output
|
||||
phpstan analyse --configuration=phpstan.neon
|
||||
|
||||
# Generate baseline to ignore existing issues
|
||||
phpstan analyse --configuration=phpstan.neon --generate-baseline
|
||||
```
|
||||
|
||||
#### PHPCS Violations
|
||||
|
||||
```bash
|
||||
# Check violations
|
||||
phpcs --standard=phpcs.xml src/
|
||||
|
||||
# Auto-fix where possible
|
||||
phpcbf --standard=phpcs.xml src/
|
||||
|
||||
# Show specific error codes
|
||||
phpcs --standard=phpcs.xml --report=source src/
|
||||
```
|
||||
|
||||
#### Joomla Testing Failed
|
||||
|
||||
1. Check PHP/Joomla version matrix compatibility
|
||||
2. Review MySQL connection errors
|
||||
3. Verify template manifest structure
|
||||
4. Check template file paths
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Version Management
|
||||
|
||||
1. **Always use version branches:** dev/X.Y.Z, rc/X.Y.Z, version/X.Y.Z
|
||||
2. **Follow hierarchy:** dev → rc → version → main
|
||||
3. **Update CHANGELOG:** Document all changes in Unreleased section
|
||||
4. **Semantic versioning:** Major.Minor.Patch (03.05.00)
|
||||
|
||||
### Code Quality
|
||||
|
||||
1. **Run validations locally** before pushing
|
||||
2. **Fix PHPStan warnings** at level 5
|
||||
3. **Follow PSR-12** coding standards
|
||||
4. **Add SPDX license headers** to new files
|
||||
5. **Keep functions small** and well-documented
|
||||
|
||||
### Workflow Usage
|
||||
|
||||
1. **Use CI for every commit** - automated validation
|
||||
2. **Run repo_health before releases** - comprehensive checks
|
||||
3. **Test on staging first** - never deploy directly to production
|
||||
4. **Monitor workflow runs** - fix failures promptly
|
||||
5. **Review workflow logs** - understand what changed
|
||||
|
||||
### Release Process
|
||||
|
||||
1. **Create dev branch** → Work on features
|
||||
2. **Promote to rc** → Release candidate testing
|
||||
3. **Promote to version** → Stable release
|
||||
4. **Merge to main** → Production (auto-merged via PR)
|
||||
5. **Create GitHub Release** → Public distribution
|
||||
|
||||
### Security
|
||||
|
||||
1. **Never commit secrets** - use GitHub Secrets
|
||||
2. **Use SSH keys** for SFTP (not passwords)
|
||||
3. **Scan for secrets** - runs automatically in CI
|
||||
4. **Keep dependencies updated** - security patches
|
||||
5. **Review security advisories** - GitHub Dependabot
|
||||
|
||||
### Documentation
|
||||
|
||||
1. **Update docs with code** - keep in sync
|
||||
2. **Document workflow changes** - update this guide
|
||||
3. **Add examples** - show, don't just tell
|
||||
4. **Link to relevant docs** - cross-reference
|
||||
5. **Keep README current** - first impression matters
|
||||
|
||||
## Quick Links
|
||||
|
||||
- [Main README](../README.md) - Project overview
|
||||
- [Joomla Development Guide](./JOOMLA_DEVELOPMENT.md) - Testing and quality
|
||||
- [Scripts README](../scripts/README.md) - Script documentation
|
||||
- [CHANGELOG](../CHANGELOG.md) - Version history
|
||||
- [CONTRIBUTING](../CONTRIBUTING.md) - Contribution guidelines
|
||||
|
||||
## Getting Help
|
||||
|
||||
1. **Check workflow logs** - Most issues have clear error messages
|
||||
2. **Review this guide** - Common solutions documented
|
||||
3. **Run validation scripts** - Identify specific issues
|
||||
4. **Open an issue** - For bugs or questions
|
||||
5. **Contact maintainers** - For access or configuration issues
|
||||
|
||||
---
|
||||
|
||||
**Document Version:** 1.0.0
|
||||
**Last Updated:** 2026-01-04
|
||||
**Maintained by:** Moko Consulting Engineering
|
||||
56
scripts/git/install-hooks.sh
Executable file
56
scripts/git/install-hooks.sh
Executable file
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env bash
|
||||
# Install Git hooks for Moko Cassiopeia
|
||||
# Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Moko-Cassiopeia.Scripts
|
||||
# INGROUP: Scripts.Git
|
||||
# REPO: https://github.com/mokoconsulting-tech/moko-cassiopeia
|
||||
# FILE: ./scripts/git/install-hooks.sh
|
||||
# VERSION: 01.00.00
|
||||
# BRIEF: Install Git hooks for local development
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
|
||||
echo "Installing Git hooks..."
|
||||
echo ""
|
||||
|
||||
# Create .git/hooks directory if it doesn't exist
|
||||
mkdir -p "${REPO_ROOT}/.git/hooks"
|
||||
|
||||
# Install pre-commit hook
|
||||
PRE_COMMIT_HOOK="${REPO_ROOT}/.git/hooks/pre-commit"
|
||||
cat > "${PRE_COMMIT_HOOK}" <<'EOF'
|
||||
#!/usr/bin/env bash
|
||||
# Pre-commit hook - installed by scripts/git/install-hooks.sh
|
||||
|
||||
SCRIPT_DIR="$(git rev-parse --show-toplevel)/scripts/git"
|
||||
|
||||
if [ -f "${SCRIPT_DIR}/pre-commit.sh" ]; then
|
||||
exec "${SCRIPT_DIR}/pre-commit.sh" "$@"
|
||||
else
|
||||
echo "Error: pre-commit.sh not found in ${SCRIPT_DIR}"
|
||||
exit 1
|
||||
fi
|
||||
EOF
|
||||
|
||||
chmod +x "${PRE_COMMIT_HOOK}"
|
||||
|
||||
echo "✓ Installed pre-commit hook"
|
||||
echo ""
|
||||
echo "The pre-commit hook will run automatically before each commit."
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " - Skip hook: git commit --no-verify"
|
||||
echo " - Quick mode: ./scripts/git/pre-commit.sh --quick"
|
||||
echo " - Skip quality checks: ./scripts/git/pre-commit.sh --skip-quality"
|
||||
echo ""
|
||||
echo "To uninstall hooks:"
|
||||
echo " rm .git/hooks/pre-commit"
|
||||
echo ""
|
||||
echo "Done!"
|
||||
270
scripts/git/pre-commit.sh
Executable file
270
scripts/git/pre-commit.sh
Executable file
@@ -0,0 +1,270 @@
|
||||
#!/usr/bin/env bash
|
||||
# Pre-commit hook script for Moko Cassiopeia
|
||||
# Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Moko-Cassiopeia.Scripts
|
||||
# INGROUP: Scripts.Git
|
||||
# REPO: https://github.com/mokoconsulting-tech/moko-cassiopeia
|
||||
# FILE: ./scripts/git/pre-commit.sh
|
||||
# VERSION: 01.00.00
|
||||
# BRIEF: Pre-commit hook for local validation
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
. "${SCRIPT_DIR}/lib/common.sh"
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}✓${NC} $*"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}⚠${NC} $*"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}✗${NC} $*"
|
||||
}
|
||||
|
||||
log_header() {
|
||||
echo ""
|
||||
echo "================================"
|
||||
echo "$*"
|
||||
echo "================================"
|
||||
}
|
||||
|
||||
# Parse arguments
|
||||
SKIP_TESTS=false
|
||||
SKIP_QUALITY=false
|
||||
QUICK_MODE=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--skip-tests)
|
||||
SKIP_TESTS=true
|
||||
shift
|
||||
;;
|
||||
--skip-quality)
|
||||
SKIP_QUALITY=true
|
||||
shift
|
||||
;;
|
||||
--quick)
|
||||
QUICK_MODE=true
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
echo "Usage: pre-commit.sh [--skip-tests] [--skip-quality] [--quick]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
log_header "Pre-commit Validation"
|
||||
|
||||
# Get list of staged files
|
||||
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACMR)
|
||||
|
||||
if [ -z "$STAGED_FILES" ]; then
|
||||
log_warning "No staged files to check"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Checking staged files:"
|
||||
echo "$STAGED_FILES" | sed 's/^/ - /'
|
||||
echo ""
|
||||
|
||||
# Track failures
|
||||
FAILURES=0
|
||||
|
||||
# Check 1: PHP Syntax
|
||||
log_header "Checking PHP Syntax"
|
||||
PHP_FILES=$(echo "$STAGED_FILES" | grep '\.php$' || true)
|
||||
|
||||
if [ -n "$PHP_FILES" ]; then
|
||||
while IFS= read -r file; do
|
||||
if [ -f "$file" ]; then
|
||||
if php -l "$file" > /dev/null 2>&1; then
|
||||
log_success "PHP syntax OK: $file"
|
||||
else
|
||||
log_error "PHP syntax error: $file"
|
||||
php -l "$file"
|
||||
FAILURES=$((FAILURES + 1))
|
||||
fi
|
||||
fi
|
||||
done <<< "$PHP_FILES"
|
||||
else
|
||||
echo " No PHP files to check"
|
||||
fi
|
||||
|
||||
# Check 2: XML Well-formedness
|
||||
log_header "Checking XML Files"
|
||||
XML_FILES=$(echo "$STAGED_FILES" | grep '\.xml$' || true)
|
||||
|
||||
if [ -n "$XML_FILES" ]; then
|
||||
while IFS= read -r file; do
|
||||
if [ -f "$file" ]; then
|
||||
if xmllint --noout "$file" 2>/dev/null; then
|
||||
log_success "XML well-formed: $file"
|
||||
else
|
||||
log_error "XML malformed: $file"
|
||||
xmllint --noout "$file" || true
|
||||
FAILURES=$((FAILURES + 1))
|
||||
fi
|
||||
fi
|
||||
done <<< "$XML_FILES"
|
||||
else
|
||||
echo " No XML files to check"
|
||||
fi
|
||||
|
||||
# Check 3: YAML Syntax
|
||||
log_header "Checking YAML Files"
|
||||
YAML_FILES=$(echo "$STAGED_FILES" | grep -E '\.(yml|yaml)$' || true)
|
||||
|
||||
if [ -n "$YAML_FILES" ]; then
|
||||
while IFS= read -r file; do
|
||||
if [ -f "$file" ]; then
|
||||
if python3 -c "import yaml; yaml.safe_load(open('$file'))" 2>/dev/null; then
|
||||
log_success "YAML valid: $file"
|
||||
else
|
||||
log_error "YAML invalid: $file"
|
||||
python3 -c "import yaml; yaml.safe_load(open('$file'))" || true
|
||||
FAILURES=$((FAILURES + 1))
|
||||
fi
|
||||
fi
|
||||
done <<< "$YAML_FILES"
|
||||
else
|
||||
echo " No YAML files to check"
|
||||
fi
|
||||
|
||||
# Check 4: Trailing Whitespace
|
||||
log_header "Checking for Trailing Whitespace"
|
||||
TEXT_FILES=$(echo "$STAGED_FILES" | grep -vE '\.(png|jpg|jpeg|gif|svg|ico|zip|gz|woff|woff2|ttf)$' || true)
|
||||
|
||||
if [ -n "$TEXT_FILES" ]; then
|
||||
TRAILING_WS=$(echo "$TEXT_FILES" | xargs grep -n '[[:space:]]$' 2>/dev/null || true)
|
||||
if [ -n "$TRAILING_WS" ]; then
|
||||
log_warning "Files with trailing whitespace found:"
|
||||
echo "$TRAILING_WS" | sed 's/^/ /'
|
||||
echo ""
|
||||
echo " Run: sed -i 's/[[:space:]]*$//' <file> to fix"
|
||||
else
|
||||
log_success "No trailing whitespace"
|
||||
fi
|
||||
else
|
||||
echo " No text files to check"
|
||||
fi
|
||||
|
||||
# Check 5: SPDX License Headers (if not quick mode)
|
||||
if [ "$QUICK_MODE" = false ]; then
|
||||
log_header "Checking SPDX License Headers"
|
||||
SOURCE_FILES=$(echo "$STAGED_FILES" | grep -E '\.(php|sh|js|ts|css)$' || true)
|
||||
|
||||
if [ -n "$SOURCE_FILES" ]; then
|
||||
MISSING_SPDX=""
|
||||
while IFS= read -r file; do
|
||||
if [ -f "$file" ]; then
|
||||
if ! head -n 20 "$file" | grep -q 'SPDX-License-Identifier:'; then
|
||||
MISSING_SPDX="${MISSING_SPDX} - ${file}\n"
|
||||
fi
|
||||
fi
|
||||
done <<< "$SOURCE_FILES"
|
||||
|
||||
if [ -n "$MISSING_SPDX" ]; then
|
||||
log_warning "Files missing SPDX license header:"
|
||||
echo -e "$MISSING_SPDX"
|
||||
else
|
||||
log_success "All source files have SPDX headers"
|
||||
fi
|
||||
else
|
||||
echo " No source files to check"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check 6: No Secrets
|
||||
log_header "Checking for Secrets"
|
||||
if [ -x "${SCRIPT_DIR}/validate/no_secrets.sh" ]; then
|
||||
if "${SCRIPT_DIR}/validate/no_secrets.sh" > /dev/null 2>&1; then
|
||||
log_success "No secrets detected"
|
||||
else
|
||||
log_error "Potential secrets detected!"
|
||||
"${SCRIPT_DIR}/validate/no_secrets.sh" || true
|
||||
FAILURES=$((FAILURES + 1))
|
||||
fi
|
||||
else
|
||||
echo " Secret scanner not available"
|
||||
fi
|
||||
|
||||
# Check 7: PHP_CodeSniffer (if not skipped)
|
||||
if [ "$SKIP_QUALITY" = false ] && command -v phpcs >/dev/null 2>&1; then
|
||||
log_header "Running PHP_CodeSniffer"
|
||||
PHP_FILES=$(echo "$STAGED_FILES" | grep '\.php$' || true)
|
||||
|
||||
if [ -n "$PHP_FILES" ]; then
|
||||
if echo "$PHP_FILES" | xargs phpcs --standard=phpcs.xml -q 2>/dev/null; then
|
||||
log_success "PHPCS passed"
|
||||
else
|
||||
log_warning "PHPCS found issues (non-blocking)"
|
||||
echo "$PHP_FILES" | xargs phpcs --standard=phpcs.xml --report=summary || true
|
||||
fi
|
||||
else
|
||||
echo " No PHP files to check"
|
||||
fi
|
||||
else
|
||||
if [ "$SKIP_QUALITY" = true ]; then
|
||||
echo " Skipping PHPCS (--skip-quality)"
|
||||
else
|
||||
echo " PHPCS not available (install with: composer global require squizlabs/php_codesniffer)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check 8: PHPStan (if not skipped and not quick mode)
|
||||
if [ "$SKIP_QUALITY" = false ] && [ "$QUICK_MODE" = false ] && command -v phpstan >/dev/null 2>&1; then
|
||||
log_header "Running PHPStan"
|
||||
PHP_FILES=$(echo "$STAGED_FILES" | grep '\.php$' || true)
|
||||
|
||||
if [ -n "$PHP_FILES" ]; then
|
||||
if phpstan analyse --configuration=phpstan.neon --no-progress > /dev/null 2>&1; then
|
||||
log_success "PHPStan passed"
|
||||
else
|
||||
log_warning "PHPStan found issues (non-blocking)"
|
||||
phpstan analyse --configuration=phpstan.neon --no-progress || true
|
||||
fi
|
||||
else
|
||||
echo " No PHP files to check"
|
||||
fi
|
||||
else
|
||||
if [ "$SKIP_QUALITY" = true ]; then
|
||||
echo " Skipping PHPStan (--skip-quality)"
|
||||
elif [ "$QUICK_MODE" = true ]; then
|
||||
echo " Skipping PHPStan (--quick mode)"
|
||||
else
|
||||
echo " PHPStan not available (install with: composer global require phpstan/phpstan)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Summary
|
||||
log_header "Pre-commit Summary"
|
||||
|
||||
if [ $FAILURES -gt 0 ]; then
|
||||
log_error "Pre-commit checks failed with $FAILURES error(s)"
|
||||
echo ""
|
||||
echo "To commit anyway, use: git commit --no-verify"
|
||||
echo "To run quick checks only: ./scripts/git/pre-commit.sh --quick"
|
||||
echo "To skip quality checks: ./scripts/git/pre-commit.sh --skip-quality"
|
||||
exit 1
|
||||
else
|
||||
log_success "All pre-commit checks passed!"
|
||||
echo ""
|
||||
echo "Tip: Use 'make validate' for comprehensive validation"
|
||||
exit 0
|
||||
fi
|
||||
Reference in New Issue
Block a user