Make /scripts/ enterprise ready #26
583
scripts/ENTERPRISE.md
Normal file
583
scripts/ENTERPRISE.md
Normal file
@@ -0,0 +1,583 @@
|
|||||||
|
<!-- Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
|
|
||||||
|
This file is part of a Moko Consulting project.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see https://www.gnu.org/licenses/ .
|
||||||
|
|
||||||
|
FILE INFORMATION
|
||||||
|
DEFGROUP: Moko-Cassiopeia.Documentation
|
||||||
|
INGROUP: Scripts.Documentation
|
||||||
|
REPO: https://github.com/mokoconsulting-tech/moko-cassiopeia
|
||||||
|
FILE: ./scripts/ENTERPRISE.md
|
||||||
|
VERSION: 01.00.00
|
||||||
|
BRIEF: Enterprise-grade scripting standards and best practices
|
||||||
|
-->
|
||||||
|
|
||||||
|
# Enterprise Standards for Scripts
|
||||||
|
|
||||||
|
This document defines the enterprise-grade standards and best practices
|
||||||
|
implemented across all automation scripts in this repository.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [Overview](#overview)
|
||||||
|
- [Core Principles](#core-principles)
|
||||||
|
- [Script Structure](#script-structure)
|
||||||
|
- [Error Handling](#error-handling)
|
||||||
|
- [Logging and Observability](#logging-and-observability)
|
||||||
|
- [Security Standards](#security-standards)
|
||||||
|
- [Dependency Management](#dependency-management)
|
||||||
|
- [Exit Codes](#exit-codes)
|
||||||
|
- [Documentation Requirements](#documentation-requirements)
|
||||||
|
- [Testing and Validation](#testing-and-validation)
|
||||||
|
- [Operational Considerations](#operational-considerations)
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
All scripts in this repository follow enterprise-grade standards to ensure:
|
||||||
|
- **Reliability**: Predictable behavior in all environments
|
||||||
|
- **Security**: Protection against vulnerabilities and credential exposure
|
||||||
|
- **Observability**: Clear logging and error reporting
|
||||||
|
- **Maintainability**: Consistent patterns and documentation
|
||||||
|
- **Portability**: Cross-platform compatibility
|
||||||
|
|
||||||
|
## Core Principles
|
||||||
|
|
||||||
|
### 1. Fail Fast, Fail Clearly
|
||||||
|
|
||||||
|
Scripts must fail immediately when encountering errors and provide clear,
|
||||||
|
actionable error messages.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
set -euo pipefail # Required at top of all bash scripts
|
||||||
|
```
|
||||||
|
|
||||||
|
- `-e`: Exit on first error
|
||||||
|
- `-u`: Exit on undefined variable reference
|
||||||
|
- `-o pipefail`: Propagate pipeline failures
|
||||||
|
|
||||||
|
### 2. Zero Assumptions
|
||||||
|
|
||||||
|
- Always validate inputs
|
||||||
|
- Check for required dependencies
|
||||||
|
- Verify file/directory existence before access
|
||||||
|
- Never assume environment state
|
||||||
|
|
||||||
|
### 3. Idempotency Where Possible
|
||||||
|
|
||||||
|
Scripts should be safe to run multiple times without causing harm or
|
||||||
|
inconsistency.
|
||||||
|
|
||||||
|
### 4. Least Privilege
|
||||||
|
|
||||||
|
Scripts should:
|
||||||
|
- Never require root unless absolutely necessary
|
||||||
|
- Use minimal file system permissions
|
||||||
|
- Validate before modifying files
|
||||||
|
|
||||||
|
## Script Structure
|
||||||
|
|
||||||
|
### Standard Header Template
|
||||||
|
|
||||||
|
Every script must include:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
|
#
|
||||||
|
# This file is part of a Moko Consulting project.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
#
|
||||||
|
# [Full license text...]
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# FILE INFORMATION
|
||||||
|
# ============================================================================
|
||||||
|
# DEFGROUP: Script.Category
|
||||||
|
# INGROUP: Subcategory
|
||||||
|
# REPO: https://github.com/mokoconsulting-tech/moko-cassiopeia
|
||||||
|
# PATH: /scripts/path/to/script.sh
|
||||||
|
# VERSION: XX.XX.XX
|
||||||
|
# BRIEF: One-line description of script purpose
|
||||||
|
# NOTE: Additional context or usage notes
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
```
|
||||||
|
|
||||||
|
### Usage Function
|
||||||
|
|
||||||
|
User-facing scripts must provide a usage/help function:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
usage() {
|
||||||
|
cat <<-USAGE
|
||||||
|
Usage: $0 [OPTIONS] <ARGS>
|
||||||
|
|
||||||
|
Description of what the script does.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-h, --help Show this help message
|
||||||
|
-v, --verbose Enable verbose output
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
ARG1 Description of first argument
|
||||||
|
ARG2 Description of second argument
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
$0 example_value
|
||||||
|
$0 -v example_value
|
||||||
|
|
||||||
|
Exit codes:
|
||||||
|
0 - Success
|
||||||
|
1 - Error
|
||||||
|
2 - Invalid arguments
|
||||||
|
|
||||||
|
USAGE
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Argument Parsing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Parse arguments
|
||||||
|
if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ $# -ge 1 ] || usage
|
||||||
|
```
|
||||||
|
|
||||||
|
### Library Sourcing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
. "${SCRIPT_DIR}/lib/common.sh"
|
||||||
|
|
||||||
|
# Check dependencies
|
||||||
|
check_dependencies python3 git
|
||||||
|
```
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
### Error Messages
|
||||||
|
|
||||||
|
Error messages must be:
|
||||||
|
- **Clear**: Explain what went wrong
|
||||||
|
- **Actionable**: Tell user how to fix it
|
||||||
|
- **Contextual**: Include relevant details
|
||||||
|
- **Verbose**: Provide comprehensive information by default
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Bad
|
||||||
|
die "Error"
|
||||||
|
|
||||||
|
# Good - Verbose with context and solutions
|
||||||
|
die "Required file not found: ${CONFIG_FILE}
|
||||||
|
|
||||||
|
Current directory: $(pwd)
|
||||||
|
Expected location: ./config/${CONFIG_FILE}
|
||||||
|
|
||||||
|
To fix:
|
||||||
|
1. Run setup script: ./scripts/setup.sh
|
||||||
|
2. Or create the file manually: touch config/${CONFIG_FILE}
|
||||||
|
"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Error Output
|
||||||
|
|
||||||
|
- Always show full error output for failed operations
|
||||||
|
- Include line numbers and file paths
|
||||||
|
- Show error summaries with troubleshooting steps
|
||||||
|
- Provide installation guides for missing dependencies
|
||||||
|
|
||||||
|
Example verbose error from validation:
|
||||||
|
```
|
||||||
|
ERROR: PHP syntax validation failed
|
||||||
|
Files checked: 90
|
||||||
|
Files with errors: 2
|
||||||
|
|
||||||
|
Failed files and errors:
|
||||||
|
File: src/test.php
|
||||||
|
Error: Parse error: syntax error, unexpected '}' in src/test.php on line 42
|
||||||
|
|
||||||
|
File: src/helper.php
|
||||||
|
Error: Parse error: syntax error, unexpected T_STRING in src/helper.php on line 15
|
||||||
|
|
||||||
|
To fix: Review and correct the syntax errors in the files listed above.
|
||||||
|
Run 'php -l <filename>' on individual files for detailed error messages.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Validation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Validate inputs
|
||||||
|
validate_version() {
|
||||||
|
local v="$1"
|
||||||
|
if ! printf '%s' "$v" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$'; then
|
||||||
|
die "Invalid version format: $v (expected X.Y.Z)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check file existence
|
||||||
|
assert_file_exists "${MANIFEST}" || die "Manifest not found: ${MANIFEST}"
|
||||||
|
|
||||||
|
# Verify directory
|
||||||
|
assert_dir_exists "${SRC_DIR}" || die "Source directory missing: ${SRC_DIR}"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Logging and Observability
|
||||||
|
|
||||||
|
### Logging Functions
|
||||||
|
|
||||||
|
Use standard logging functions from `lib/common.sh`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
log_info "Starting process..." # Informational messages
|
||||||
|
log_warn "Configuration missing" # Warnings (non-fatal)
|
||||||
|
log_error "Validation failed" # Errors (fatal)
|
||||||
|
die "Critical error occurred" # Fatal with exit
|
||||||
|
```
|
||||||
|
|
||||||
|
### Timestamps
|
||||||
|
|
||||||
|
Include timestamps for audit trails:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
log_info "Start time: $(log_timestamp)"
|
||||||
|
# ... work ...
|
||||||
|
log_info "End time: $(log_timestamp)"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Structured Output
|
||||||
|
|
||||||
|
For machine-readable output, use JSON:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
printf '{"status":"ok","files_checked":%s}\n' "${count}"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Progress Reporting
|
||||||
|
|
||||||
|
For long-running operations:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
log_section "Phase 1: Validation"
|
||||||
|
log_step "Checking manifests..."
|
||||||
|
log_success "✓ Manifests valid"
|
||||||
|
log_kv "Files processed" "${count}"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Standards
|
||||||
|
|
||||||
|
### 1. No Hardcoded Secrets
|
||||||
|
|
||||||
|
- Never commit credentials
|
||||||
|
- Use environment variables for sensitive data
|
||||||
|
- Validate against secret patterns
|
||||||
|
|
||||||
|
### 2. Input Sanitization
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Validate user input
|
||||||
|
if [[ "${input}" =~ [^a-zA-Z0-9._-] ]]; then
|
||||||
|
die "Invalid input: contains disallowed characters"
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. File Operations
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Use explicit paths
|
||||||
|
FILE="/full/path/to/file"
|
||||||
|
|
||||||
|
# Avoid user-controlled paths without validation
|
||||||
|
# Validate before rm/mv operations
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Command Injection Prevention
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Use arrays for command arguments
|
||||||
|
args=("$file1" "$file2")
|
||||||
|
command "${args[@]}"
|
||||||
|
|
||||||
|
# Quote all variables
|
||||||
|
grep "${pattern}" "${file}"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dependency Management
|
||||||
|
|
||||||
|
### Required Dependencies Check
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# At script start
|
||||||
|
check_dependencies python3 git sed
|
||||||
|
|
||||||
|
# Or inline
|
||||||
|
require_cmd xmllint || die "xmllint not available"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Graceful Degradation
|
||||||
|
|
||||||
|
When optional dependencies are missing:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
if ! command -v php >/dev/null 2>&1; then
|
||||||
|
log_warn "PHP not available, skipping syntax check"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
## Exit Codes
|
||||||
|
|
||||||
|
Standard exit codes across all scripts:
|
||||||
|
|
||||||
|
| Code | Meaning | Usage |
|
||||||
|
|------|---------|-------|
|
||||||
|
| 0 | Success | All operations completed successfully |
|
||||||
|
| 1 | Error | Fatal error occurred |
|
||||||
|
| 2 | Invalid arguments | Bad command-line arguments or usage |
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Success
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
# Fatal error
|
||||||
|
die "Error message" # Exits with code 1
|
||||||
|
|
||||||
|
# Invalid arguments
|
||||||
|
usage # Exits with code 0 (help shown)
|
||||||
|
# or
|
||||||
|
log_error "Invalid argument"
|
||||||
|
exit 2
|
||||||
|
```
|
||||||
|
|
||||||
|
## Documentation Requirements
|
||||||
|
|
||||||
|
### 1. Script Headers
|
||||||
|
|
||||||
|
Must include:
|
||||||
|
- Copyright notice
|
||||||
|
- SPDX license identifier
|
||||||
|
- FILE INFORMATION section
|
||||||
|
- Version number
|
||||||
|
- Brief description
|
||||||
|
|
||||||
|
### 2. Inline Comments
|
||||||
|
|
||||||
|
Use comments for:
|
||||||
|
- Complex logic explanation
|
||||||
|
- Why decisions were made (not what code does)
|
||||||
|
- Security considerations
|
||||||
|
- Performance notes
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Use git ls-files for performance vs. find
|
||||||
|
files=$(git ls-files '*.yml' '*.yaml')
|
||||||
|
|
||||||
|
# NOTE: Binary detection prevents corrupting image files
|
||||||
|
if file --mime-type "$f" | grep -q '^application/'; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. README Documentation
|
||||||
|
|
||||||
|
Update `scripts/README.md` when:
|
||||||
|
- Adding new scripts
|
||||||
|
- Changing script behavior
|
||||||
|
- Adding new library functions
|
||||||
|
|
||||||
|
## Testing and Validation
|
||||||
|
|
||||||
|
### Self-Testing
|
||||||
|
|
||||||
|
Scripts should validate their own requirements:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Validate environment
|
||||||
|
[ -d "${SRC_DIR}" ] || die "Source directory not found"
|
||||||
|
|
||||||
|
# Validate configuration
|
||||||
|
[ -n "${VERSION}" ] || die "VERSION must be set"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Script Health Checking
|
||||||
|
|
||||||
|
Use the script health checker to validate all scripts follow standards:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/run/script_health.sh # Check all scripts
|
||||||
|
./scripts/run/script_health.sh -v # Verbose mode with details
|
||||||
|
```
|
||||||
|
|
||||||
|
The health checker validates:
|
||||||
|
- Copyright headers present
|
||||||
|
- SPDX license identifiers
|
||||||
|
- FILE INFORMATION sections
|
||||||
|
- Error handling (set -euo pipefail)
|
||||||
|
- Executable permissions
|
||||||
|
|
||||||
|
### Integration Testing
|
||||||
|
|
||||||
|
Run validation suite before commits:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/run/validate_all.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Smoke Testing
|
||||||
|
|
||||||
|
Basic health checks:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/run/smoke_test.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Operational Considerations
|
||||||
|
|
||||||
|
### 1. Timeout Handling
|
||||||
|
|
||||||
|
For long-running operations:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
run_with_timeout 300 long_running_command
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Cleanup
|
||||||
|
|
||||||
|
Use traps for cleanup:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cleanup() {
|
||||||
|
rm -f "${TEMP_FILE}"
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Lock Files
|
||||||
|
|
||||||
|
For singleton operations:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
LOCK_FILE="/tmp/script.lock"
|
||||||
|
if [ -f "${LOCK_FILE}" ]; then
|
||||||
|
die "Script already running (lock file exists)"
|
||||||
|
fi
|
||||||
|
touch "${LOCK_FILE}"
|
||||||
|
trap "rm -f ${LOCK_FILE}" EXIT
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Signal Handling
|
||||||
|
|
||||||
|
```bash
|
||||||
|
handle_interrupt() {
|
||||||
|
log_warn "Interrupted by user"
|
||||||
|
cleanup
|
||||||
|
exit 130
|
||||||
|
}
|
||||||
|
trap handle_interrupt INT TERM
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Dry Run Mode
|
||||||
|
|
||||||
|
For destructive operations:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
DRY_RUN="${DRY_RUN:-false}"
|
||||||
|
|
||||||
|
if [ "${DRY_RUN}" = "true" ]; then
|
||||||
|
log_info "DRY RUN: Would execute: $command"
|
||||||
|
else
|
||||||
|
"$command"
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
## CI/CD Integration
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
Scripts should respect:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
CI="${CI:-false}" # Running in CI
|
||||||
|
VERBOSE="${VERBOSE:-false}" # Verbose output
|
||||||
|
DEBUG="${DEBUG:-false}" # Debug mode
|
||||||
|
```
|
||||||
|
|
||||||
|
### CI-Specific Behavior
|
||||||
|
|
||||||
|
```bash
|
||||||
|
if is_ci; then
|
||||||
|
# CI-specific settings
|
||||||
|
set -x # Echo commands for debugging
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
### Job Summaries
|
||||||
|
|
||||||
|
For GitHub Actions:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
if [ -n "${GITHUB_STEP_SUMMARY:-}" ]; then
|
||||||
|
echo "### Validation Results" >> "$GITHUB_STEP_SUMMARY"
|
||||||
|
echo "Status: PASSED" >> "$GITHUB_STEP_SUMMARY"
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
## Review Checklist
|
||||||
|
|
||||||
|
Before committing new or modified scripts:
|
||||||
|
|
||||||
|
- [ ] Includes proper copyright header
|
||||||
|
- [ ] Uses `set -euo pipefail`
|
||||||
|
- [ ] Has usage/help function (if user-facing)
|
||||||
|
- [ ] Validates all inputs
|
||||||
|
- [ ] Checks dependencies with `check_dependencies`
|
||||||
|
- [ ] Uses structured logging (`log_info`, `log_error`, etc.)
|
||||||
|
- [ ] Includes timestamps for audit trails
|
||||||
|
- [ ] Returns appropriate exit codes (0=success, 1=error, 2=invalid args)
|
||||||
|
- [ ] Includes inline comments for complex logic
|
||||||
|
- [ ] Documented in scripts/README.md
|
||||||
|
- [ ] Tested locally
|
||||||
|
- [ ] Passes `./scripts/run/script_health.sh`
|
||||||
|
- [ ] Passes all validation checks (`./scripts/run/validate_all.sh`)
|
||||||
|
- [ ] Passes `shellcheck` (if available)
|
||||||
|
|
||||||
|
Quick validation command:
|
||||||
|
```bash
|
||||||
|
# Run all checks
|
||||||
|
./scripts/run/script_health.sh && ./scripts/run/validate_all.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Version History
|
||||||
|
|
||||||
|
| Version | Date | Description |
|
||||||
|
| ------- | ---------- | ----------- |
|
||||||
|
| 01.00.00 | 2025-01-03 | Initial enterprise standards documentation |
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
|
||||||
|
- **Document:** scripts/ENTERPRISE.md
|
||||||
|
- **Repository:** https://github.com/mokoconsulting-tech/moko-cassiopeia
|
||||||
|
- **Version:** 01.00.00
|
||||||
|
- **Status:** Active
|
||||||
@@ -253,8 +253,46 @@ WARN: ✗ tabs (warnings/issues found - run with -v for details)
|
|||||||
[SUCCESS] SUCCESS: All required checks passed
|
[SUCCESS] SUCCESS: All required checks passed
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `script_health.sh`
|
||||||
|
Validates that all scripts follow enterprise standards:
|
||||||
|
- Checks for copyright headers
|
||||||
|
- Validates SPDX license identifiers
|
||||||
|
- Ensures FILE INFORMATION sections are present
|
||||||
|
- Verifies error handling (set -euo pipefail)
|
||||||
|
- Checks executable permissions
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
```bash
|
||||||
|
./scripts/run/script_health.sh # Standard mode
|
||||||
|
./scripts/run/script_health.sh -v # Verbose mode (shows details)
|
||||||
|
```
|
||||||
|
|
||||||
|
Example output:
|
||||||
|
```
|
||||||
|
=== Script Health Summary ===
|
||||||
|
Total scripts checked: 21
|
||||||
|
Missing copyright: 0
|
||||||
|
Missing SPDX identifier: 0
|
||||||
|
Missing FILE INFORMATION: 0
|
||||||
|
Missing error handling: 0
|
||||||
|
Not executable: 0
|
||||||
|
[SUCCESS] SUCCESS: All scripts follow enterprise standards
|
||||||
|
```
|
||||||
|
|
||||||
## Best Practices
|
## Best Practices
|
||||||
|
|
||||||
|
### Enterprise Standards
|
||||||
|
|
||||||
|
For comprehensive enterprise-grade scripting standards, see
|
||||||
|
[ENTERPRISE.md](./ENTERPRISE.md).
|
||||||
|
|
||||||
|
Key highlights:
|
||||||
|
- **Error Handling**: Fail fast with clear, actionable messages
|
||||||
|
- **Security**: Input validation, no hardcoded secrets
|
||||||
|
- **Logging**: Structured output with timestamps
|
||||||
|
- **Portability**: Cross-platform compatibility
|
||||||
|
- **Documentation**: Usage functions and inline comments
|
||||||
|
|
||||||
### Writing New Scripts
|
### Writing New Scripts
|
||||||
|
|
||||||
1. **Use the library functions**:
|
1. **Use the library functions**:
|
||||||
@@ -313,6 +351,51 @@ Scripts are automatically executed in GitHub Actions workflows:
|
|||||||
- `.github/workflows/ci.yml` - Continuous integration
|
- `.github/workflows/ci.yml` - Continuous integration
|
||||||
- `.github/workflows/repo_health.yml` - Repository health checks
|
- `.github/workflows/repo_health.yml` - Repository health checks
|
||||||
|
|
||||||
|
## Enterprise Features
|
||||||
|
|
||||||
|
The scripts in this repository follow enterprise-grade standards:
|
||||||
|
|
||||||
|
### Dependency Checking
|
||||||
|
|
||||||
|
Scripts validate required dependencies at startup using `check_dependencies`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
check_dependencies python3 git sed
|
||||||
|
```
|
||||||
|
|
||||||
|
### Timestamp Logging
|
||||||
|
|
||||||
|
All major operations include timestamps for audit trails:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
log_info "Start time: $(log_timestamp)"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Usage Documentation
|
||||||
|
|
||||||
|
All user-facing scripts include comprehensive help:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/run/validate_all.sh --help
|
||||||
|
./scripts/fix/versions.sh --help
|
||||||
|
```
|
||||||
|
|
||||||
|
### Standardized Exit Codes
|
||||||
|
|
||||||
|
- `0` - Success
|
||||||
|
- `1` - Fatal error
|
||||||
|
- `2` - Invalid arguments
|
||||||
|
|
||||||
|
### Enhanced Error Messages
|
||||||
|
|
||||||
|
Clear, actionable error messages with context:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
die "Required file not found: ${CONFIG_FILE}. Run setup first."
|
||||||
|
```
|
||||||
|
|
||||||
|
See [ENTERPRISE.md](./ENTERPRISE.md) for complete standards documentation.
|
||||||
|
|
||||||
## Version History
|
## Version History
|
||||||
|
|
||||||
| Version | Date | Description |
|
| Version | Date | Description |
|
||||||
|
|||||||
@@ -54,8 +54,19 @@ Arguments:
|
|||||||
Examples:
|
Examples:
|
||||||
$0 3.5.0
|
$0 3.5.0
|
||||||
$0 1.2.3
|
$0 1.2.3
|
||||||
|
|
||||||
|
Exit codes:
|
||||||
|
0 - Version updated successfully
|
||||||
|
1 - Invalid version format or update failed
|
||||||
|
2 - Invalid arguments
|
||||||
|
|
||||||
|
Files updated:
|
||||||
|
- Joomla manifest XML (<version> tag)
|
||||||
|
- package.json (if present)
|
||||||
|
- README.md (VERSION: references, if present)
|
||||||
|
|
||||||
USAGE
|
USAGE
|
||||||
exit 1
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
validate_version() {
|
validate_version() {
|
||||||
@@ -69,12 +80,21 @@ fi
|
|||||||
# Main
|
# Main
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
[ $# -eq 1 ] || usage
|
[ $# -eq 1 ] || usage
|
||||||
|
|
||||||
VERSION="$1"
|
VERSION="$1"
|
||||||
validate_version "${VERSION}"
|
validate_version "${VERSION}"
|
||||||
|
|
||||||
|
# Check dependencies
|
||||||
|
check_dependencies python3
|
||||||
|
|
||||||
log_info "Updating version to: ${VERSION}"
|
log_info "Updating version to: ${VERSION}"
|
||||||
|
log_info "Start time: $(log_timestamp)"
|
||||||
|
|
||||||
# Source Joomla manifest utilities
|
# Source Joomla manifest utilities
|
||||||
. "${SCRIPT_DIR}/lib/joomla_manifest.sh"
|
. "${SCRIPT_DIR}/lib/joomla_manifest.sh"
|
||||||
@@ -149,6 +169,7 @@ fi
|
|||||||
|
|
||||||
log_info "========================================="
|
log_info "========================================="
|
||||||
log_info "Version update completed: ${VERSION}"
|
log_info "Version update completed: ${VERSION}"
|
||||||
|
log_info "End time: $(log_timestamp)"
|
||||||
log_info "Files updated:"
|
log_info "Files updated:"
|
||||||
log_info " - ${MANIFEST}"
|
log_info " - ${MANIFEST}"
|
||||||
[ -f "package.json" ] && log_info " - package.json"
|
[ -f "package.json" ] && log_info " - package.json"
|
||||||
|
|||||||
@@ -71,6 +71,20 @@ log_error() {
|
|||||||
|
|
||||||
die() {
|
die() {
|
||||||
log_error "$*"
|
log_error "$*"
|
||||||
|
if [ "${VERBOSE_ERRORS:-true}" = "true" ]; then
|
||||||
|
echo "" >&2
|
||||||
|
echo "Stack trace (last 10 commands):" >&2
|
||||||
|
if [ -n "${BASH_VERSION:-}" ]; then
|
||||||
|
history | tail -10 >&2 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
echo "" >&2
|
||||||
|
echo "Environment:" >&2
|
||||||
|
echo " PWD: $(pwd)" >&2
|
||||||
|
echo " USER: ${USER:-unknown}" >&2
|
||||||
|
echo " SHELL: ${SHELL:-unknown}" >&2
|
||||||
|
echo " CI: ${CI:-false}" >&2
|
||||||
|
echo "" >&2
|
||||||
|
fi
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,3 +150,84 @@ PY
|
|||||||
fail_if_root() {
|
fail_if_root() {
|
||||||
[ "$(id -u)" -eq 0 ] && die "Script must not run as root"
|
[ "$(id -u)" -eq 0 ] && die "Script must not run as root"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Enterprise features
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Check for required dependencies at script start
|
||||||
|
check_dependencies() {
|
||||||
|
local missing=0
|
||||||
|
local missing_cmds=()
|
||||||
|
|
||||||
|
for cmd in "$@"; do
|
||||||
|
if ! command -v "$cmd" >/dev/null 2>&1; then
|
||||||
|
log_error "Required command not found: $cmd"
|
||||||
|
missing=$((missing + 1))
|
||||||
|
missing_cmds+=("$cmd")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$missing" -gt 0 ]; then
|
||||||
|
echo "" >&2
|
||||||
|
echo "Missing required dependencies:" >&2
|
||||||
|
for cmd in "${missing_cmds[@]}"; do
|
||||||
|
echo " - $cmd" >&2
|
||||||
|
done
|
||||||
|
echo "" >&2
|
||||||
|
echo "Installation guides:" >&2
|
||||||
|
for cmd in "${missing_cmds[@]}"; do
|
||||||
|
case "$cmd" in
|
||||||
|
python3)
|
||||||
|
echo " python3: apt-get install python3 (Debian/Ubuntu) or brew install python3 (macOS)" >&2
|
||||||
|
;;
|
||||||
|
git)
|
||||||
|
echo " git: apt-get install git (Debian/Ubuntu) or brew install git (macOS)" >&2
|
||||||
|
;;
|
||||||
|
php)
|
||||||
|
echo " php: apt-get install php-cli (Debian/Ubuntu) or brew install php (macOS)" >&2
|
||||||
|
;;
|
||||||
|
xmllint)
|
||||||
|
echo " xmllint: apt-get install libxml2-utils (Debian/Ubuntu) or brew install libxml2 (macOS)" >&2
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo " $cmd: Please install via your system package manager" >&2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
echo "" >&2
|
||||||
|
die "Missing $missing required command(s)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Timeout wrapper for long-running commands
|
||||||
|
run_with_timeout() {
|
||||||
|
local timeout="$1"
|
||||||
|
shift
|
||||||
|
if command -v timeout >/dev/null 2>&1; then
|
||||||
|
timeout "$timeout" "$@"
|
||||||
|
else
|
||||||
|
"$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add script execution timestamp
|
||||||
|
log_timestamp() {
|
||||||
|
if command -v date >/dev/null 2>&1; then
|
||||||
|
printf '%s\n' "$(date -u '+%Y-%m-%d %H:%M:%S UTC')"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Calculate and log execution duration
|
||||||
|
log_duration() {
|
||||||
|
local start="$1"
|
||||||
|
local end="$2"
|
||||||
|
local duration=$((end - start))
|
||||||
|
if [ "$duration" -ge 60 ]; then
|
||||||
|
local minutes=$((duration / 60))
|
||||||
|
local seconds=$((duration % 60))
|
||||||
|
printf '%dm %ds\n' "$minutes" "$seconds"
|
||||||
|
else
|
||||||
|
printf '%ds\n' "$duration"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|||||||
198
scripts/run/script_health.sh
Executable file
198
scripts/run/script_health.sh
Executable file
@@ -0,0 +1,198 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
|
#
|
||||||
|
# This file is part of a Moko Consulting project.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program (./LICENSE.md).
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# FILE INFORMATION
|
||||||
|
# ============================================================================
|
||||||
|
# DEFGROUP: Script.Validate
|
||||||
|
# INGROUP: Script.Health
|
||||||
|
# REPO: https://github.com/mokoconsulting-tech/moko-cassiopeia
|
||||||
|
# PATH: /scripts/run/script_health.sh
|
||||||
|
# VERSION: 01.00.00
|
||||||
|
# BRIEF: Validate scripts follow enterprise standards
|
||||||
|
# NOTE: Checks for copyright headers, error handling, and documentation
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
. "${SCRIPT_DIR}/lib/common.sh"
|
||||||
|
. "${SCRIPT_DIR}/lib/logging.sh"
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Usage
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<-USAGE
|
||||||
|
Usage: $0 [OPTIONS]
|
||||||
|
|
||||||
|
Validate that all scripts follow enterprise standards.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-v, --verbose Show detailed output
|
||||||
|
-h, --help Show this help message
|
||||||
|
|
||||||
|
Checks performed:
|
||||||
|
- Copyright headers present
|
||||||
|
- SPDX license identifier present
|
||||||
|
- FILE INFORMATION section present
|
||||||
|
- set -euo pipefail present
|
||||||
|
- Executable permissions set
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
$0 # Run all health checks
|
||||||
|
$0 -v # Verbose output
|
||||||
|
$0 --help # Show usage
|
||||||
|
|
||||||
|
Exit codes:
|
||||||
|
0 - All checks passed
|
||||||
|
1 - One or more checks failed
|
||||||
|
2 - Invalid arguments
|
||||||
|
|
||||||
|
USAGE
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Configuration
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
VERBOSE="${1:-}"
|
||||||
|
|
||||||
|
case "${VERBOSE}" in
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
-v|--verbose)
|
||||||
|
VERBOSE="true"
|
||||||
|
;;
|
||||||
|
"")
|
||||||
|
VERBOSE="false"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
log_error "Invalid argument: ${VERBOSE}"
|
||||||
|
echo ""
|
||||||
|
usage
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
log_info "Running script health checks"
|
||||||
|
log_info "Start time: $(log_timestamp)"
|
||||||
|
|
||||||
|
START_TIME=$(date +%s)
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Health checks
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
total_scripts=0
|
||||||
|
missing_copyright=0
|
||||||
|
missing_spdx=0
|
||||||
|
missing_fileinfo=0
|
||||||
|
missing_error_handling=0
|
||||||
|
not_executable=0
|
||||||
|
|
||||||
|
check_script() {
|
||||||
|
local script="$1"
|
||||||
|
local errors=0
|
||||||
|
|
||||||
|
total_scripts=$((total_scripts + 1))
|
||||||
|
|
||||||
|
# Check for copyright
|
||||||
|
if ! grep -q "Copyright (C)" "$script"; then
|
||||||
|
missing_copyright=$((missing_copyright + 1))
|
||||||
|
errors=$((errors + 1))
|
||||||
|
[ "${VERBOSE}" = "true" ] && log_warn "Missing copyright: $script"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for SPDX
|
||||||
|
if ! grep -q "SPDX-License-Identifier" "$script"; then
|
||||||
|
missing_spdx=$((missing_spdx + 1))
|
||||||
|
errors=$((errors + 1))
|
||||||
|
[ "${VERBOSE}" = "true" ] && log_warn "Missing SPDX: $script"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for FILE INFORMATION
|
||||||
|
if ! grep -q "FILE INFORMATION" "$script"; then
|
||||||
|
missing_fileinfo=$((missing_fileinfo + 1))
|
||||||
|
errors=$((errors + 1))
|
||||||
|
[ "${VERBOSE}" = "true" ] && log_warn "Missing FILE INFORMATION: $script"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for error handling (bash scripts only)
|
||||||
|
if [[ "$script" == *.sh ]]; then
|
||||||
|
if ! grep -q "set -e" "$script"; then
|
||||||
|
missing_error_handling=$((missing_error_handling + 1))
|
||||||
|
errors=$((errors + 1))
|
||||||
|
[ "${VERBOSE}" = "true" ] && log_warn "Missing error handling: $script"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check executable permission
|
||||||
|
if [ ! -x "$script" ]; then
|
||||||
|
not_executable=$((not_executable + 1))
|
||||||
|
errors=$((errors + 1))
|
||||||
|
[ "${VERBOSE}" = "true" ] && log_warn "Not executable: $script"
|
||||||
|
fi
|
||||||
|
|
||||||
|
return $errors
|
||||||
|
}
|
||||||
|
|
||||||
|
# Find all shell scripts
|
||||||
|
log_info "Scanning scripts directory..."
|
||||||
|
|
||||||
|
while IFS= read -r -d '' script; do
|
||||||
|
check_script "$script" || true
|
||||||
|
done < <(find "${SCRIPT_DIR}" -type f -name "*.sh" -print0)
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Summary
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
END_TIME=$(date +%s)
|
||||||
|
|
||||||
|
log_separator
|
||||||
|
log_info "Script Health Summary"
|
||||||
|
log_separator
|
||||||
|
log_kv "Total scripts checked" "${total_scripts}"
|
||||||
|
log_kv "Missing copyright" "${missing_copyright}"
|
||||||
|
log_kv "Missing SPDX identifier" "${missing_spdx}"
|
||||||
|
log_kv "Missing FILE INFORMATION" "${missing_fileinfo}"
|
||||||
|
log_kv "Missing error handling" "${missing_error_handling}"
|
||||||
|
log_kv "Not executable" "${not_executable}"
|
||||||
|
log_separator
|
||||||
|
log_info "End time: $(log_timestamp)"
|
||||||
|
log_info "Duration: $(log_duration "$START_TIME" "$END_TIME")"
|
||||||
|
|
||||||
|
total_issues=$((missing_copyright + missing_spdx + missing_fileinfo + missing_error_handling + not_executable))
|
||||||
|
|
||||||
|
if [ "$total_issues" -eq 0 ]; then
|
||||||
|
log_success "SUCCESS: All scripts follow enterprise standards"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
log_error "FAILED: Found ${total_issues} standard violation(s)"
|
||||||
|
log_info "Run with -v flag for details on which scripts need updates"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@@ -35,11 +35,43 @@
|
|||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Usage
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<-USAGE
|
||||||
|
Usage: $0 [OPTIONS]
|
||||||
|
|
||||||
|
Run basic smoke tests to verify repository structure and manifest validity.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-h, --help Show this help message
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
$0 # Run all smoke tests
|
||||||
|
$0 --help # Show usage information
|
||||||
|
|
||||||
|
USAGE
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
# Source common utilities
|
# Source common utilities
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
. "${SCRIPT_DIR}/lib/common.sh"
|
. "${SCRIPT_DIR}/lib/common.sh"
|
||||||
|
|
||||||
|
# Check dependencies
|
||||||
|
check_dependencies python3
|
||||||
|
|
||||||
|
START_TIME=$(date +%s)
|
||||||
|
|
||||||
log_info "Running smoke tests for Moko-Cassiopeia repository"
|
log_info "Running smoke tests for Moko-Cassiopeia repository"
|
||||||
|
log_info "Start time: $(log_timestamp)"
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
# Test: Repository structure
|
# Test: Repository structure
|
||||||
@@ -118,16 +150,29 @@ log_info "Checking PHP syntax..."
|
|||||||
|
|
||||||
if command -v php >/dev/null 2>&1; then
|
if command -v php >/dev/null 2>&1; then
|
||||||
php_errors=0
|
php_errors=0
|
||||||
|
failed_files=()
|
||||||
while IFS= read -r -d '' f; do
|
while IFS= read -r -d '' f; do
|
||||||
if ! php -l "$f" >/dev/null 2>&1; then
|
if ! php_output=$(php -l "$f" 2>&1); then
|
||||||
log_error "PHP syntax error in: $f"
|
log_error "PHP syntax error in: $f"
|
||||||
|
echo " Error details:" >&2
|
||||||
|
echo "$php_output" | sed 's/^/ /' >&2
|
||||||
|
echo "" >&2
|
||||||
php_errors=$((php_errors + 1))
|
php_errors=$((php_errors + 1))
|
||||||
|
failed_files+=("$f")
|
||||||
fi
|
fi
|
||||||
done < <(find src -type f -name '*.php' -print0 2>/dev/null)
|
done < <(find src -type f -name '*.php' -print0 2>/dev/null)
|
||||||
|
|
||||||
if [ "${php_errors}" -eq 0 ]; then
|
if [ "${php_errors}" -eq 0 ]; then
|
||||||
log_info "✓ PHP syntax validation passed"
|
log_info "✓ PHP syntax validation passed"
|
||||||
else
|
else
|
||||||
|
echo "Summary of PHP syntax errors:" >&2
|
||||||
|
echo " Total errors: ${php_errors}" >&2
|
||||||
|
echo " Failed files:" >&2
|
||||||
|
for f in "${failed_files[@]}"; do
|
||||||
|
echo " - $f" >&2
|
||||||
|
done
|
||||||
|
echo "" >&2
|
||||||
|
echo "To fix: Run 'php -l <filename>' on each failed file for detailed error messages." >&2
|
||||||
die "Found ${php_errors} PHP syntax errors"
|
die "Found ${php_errors} PHP syntax errors"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
@@ -143,4 +188,7 @@ log_info "Smoke tests completed successfully"
|
|||||||
log_info "Extension: ${NAME}"
|
log_info "Extension: ${NAME}"
|
||||||
log_info "Version: ${VERSION}"
|
log_info "Version: ${VERSION}"
|
||||||
log_info "Type: ${TYPE}"
|
log_info "Type: ${TYPE}"
|
||||||
|
log_info "End time: $(log_timestamp)"
|
||||||
|
END_TIME=$(date +%s)
|
||||||
|
log_info "Duration: $(log_duration "$START_TIME" "$END_TIME")"
|
||||||
log_info "========================================="
|
log_info "========================================="
|
||||||
|
|||||||
@@ -39,16 +39,65 @@ SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|||||||
. "${SCRIPT_DIR}/lib/common.sh"
|
. "${SCRIPT_DIR}/lib/common.sh"
|
||||||
. "${SCRIPT_DIR}/lib/logging.sh"
|
. "${SCRIPT_DIR}/lib/logging.sh"
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Usage
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<-USAGE
|
||||||
|
Usage: $0 [OPTIONS]
|
||||||
|
|
||||||
|
Run all validation scripts and report results.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-v, --verbose Show detailed output from validation scripts
|
||||||
|
-h, --help Show this help message
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
$0 # Run all validations in quiet mode
|
||||||
|
$0 -v # Run with verbose output
|
||||||
|
$0 --help # Show usage information
|
||||||
|
|
||||||
|
Exit codes:
|
||||||
|
0 - All required checks passed
|
||||||
|
1 - One or more required checks failed
|
||||||
|
2 - Invalid arguments
|
||||||
|
|
||||||
|
USAGE
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
# Configuration
|
# Configuration
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
VERBOSE="${1:-}"
|
VERBOSE="${1:-}"
|
||||||
if [ "${VERBOSE}" = "-v" ] || [ "${VERBOSE}" = "--verbose" ]; then
|
|
||||||
VERBOSE="true"
|
# Parse arguments
|
||||||
else
|
case "${VERBOSE}" in
|
||||||
VERBOSE="false"
|
-h|--help)
|
||||||
fi
|
usage
|
||||||
|
;;
|
||||||
|
-v|--verbose)
|
||||||
|
VERBOSE="true"
|
||||||
|
;;
|
||||||
|
"")
|
||||||
|
VERBOSE="false"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
log_error "Invalid argument: ${VERBOSE}"
|
||||||
|
echo ""
|
||||||
|
usage
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Check dependencies
|
||||||
|
check_dependencies python3
|
||||||
|
|
||||||
|
START_TIME=$(date +%s)
|
||||||
|
|
||||||
|
log_info "Start time: $(log_timestamp)"
|
||||||
|
|
||||||
REQUIRED_CHECKS=(
|
REQUIRED_CHECKS=(
|
||||||
"manifest"
|
"manifest"
|
||||||
@@ -90,22 +139,20 @@ for check in "${REQUIRED_CHECKS[@]}"; do
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
log_step "Running: ${check}"
|
log_step "Running: ${check}"
|
||||||
if [ "${VERBOSE}" = "true" ]; then
|
# Always capture output for better error reporting
|
||||||
if "${script}"; then
|
output=""
|
||||||
log_success "✓ ${check}"
|
if output=$("${script}" 2>&1); then
|
||||||
required_passed=$((required_passed + 1))
|
log_success "✓ ${check}"
|
||||||
else
|
required_passed=$((required_passed + 1))
|
||||||
log_error "✗ ${check} (FAILED)"
|
[ "${VERBOSE}" = "true" ] && echo "$output"
|
||||||
required_failed=$((required_failed + 1))
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
if "${script}" >/dev/null 2>&1; then
|
log_error "✗ ${check} (FAILED)"
|
||||||
log_success "✓ ${check}"
|
required_failed=$((required_failed + 1))
|
||||||
required_passed=$((required_passed + 1))
|
# Show error output for required checks regardless of verbose flag
|
||||||
else
|
echo "" >&2
|
||||||
log_error "✗ ${check} (FAILED - run with -v for details)"
|
echo "Error output:" >&2
|
||||||
required_failed=$((required_failed + 1))
|
echo "$output" >&2
|
||||||
fi
|
echo "" >&2
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -121,21 +168,27 @@ for check in "${OPTIONAL_CHECKS[@]}"; do
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
log_step "Running: ${check}"
|
log_step "Running: ${check}"
|
||||||
if [ "${VERBOSE}" = "true" ]; then
|
# Capture output for better error reporting
|
||||||
if "${script}"; then
|
output=""
|
||||||
log_success "✓ ${check}"
|
if output=$("${script}" 2>&1); then
|
||||||
optional_passed=$((optional_passed + 1))
|
log_success "✓ ${check}"
|
||||||
else
|
optional_passed=$((optional_passed + 1))
|
||||||
log_warn "✗ ${check} (warnings/issues found)"
|
[ "${VERBOSE}" = "true" ] && echo "$output"
|
||||||
optional_failed=$((optional_failed + 1))
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
if "${script}" >/dev/null 2>&1; then
|
log_warn "✗ ${check} (warnings/issues found)"
|
||||||
log_success "✓ ${check}"
|
optional_failed=$((optional_failed + 1))
|
||||||
optional_passed=$((optional_passed + 1))
|
# Show brief error summary for optional checks, full output in verbose
|
||||||
|
if [ "${VERBOSE}" = "true" ]; then
|
||||||
|
echo "" >&2
|
||||||
|
echo "Error output:" >&2
|
||||||
|
echo "$output" >&2
|
||||||
|
echo "" >&2
|
||||||
else
|
else
|
||||||
log_warn "✗ ${check} (warnings/issues found - run with -v for details)"
|
# Show first few lines of error
|
||||||
optional_failed=$((optional_failed + 1))
|
echo "" >&2
|
||||||
|
echo "Error summary (run with -v for full details):" >&2
|
||||||
|
echo "$output" | head -5 >&2
|
||||||
|
echo "" >&2
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
@@ -156,6 +209,10 @@ log_kv "Optional checks with issues" "${optional_failed}"
|
|||||||
|
|
||||||
log_separator
|
log_separator
|
||||||
|
|
||||||
|
log_info "End time: $(log_timestamp)"
|
||||||
|
END_TIME=$(date +%s)
|
||||||
|
log_info "Duration: $(log_duration "$START_TIME" "$END_TIME")"
|
||||||
|
|
||||||
if [ "${required_failed}" -gt 0 ]; then
|
if [ "${required_failed}" -gt 0 ]; then
|
||||||
log_error "FAILED: ${required_failed} required check(s) failed"
|
log_error "FAILED: ${required_failed} required check(s) failed"
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
@@ -1,4 +1,38 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
|
#
|
||||||
|
# This file is part of a Moko Consulting project.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program (./LICENSE.md).
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# FILE INFORMATION
|
||||||
|
# ============================================================================
|
||||||
|
# DEFGROUP: Script.Validate
|
||||||
|
# INGROUP: Documentation
|
||||||
|
# REPO: https://github.com/mokoconsulting-tech/moko-cassiopeia
|
||||||
|
# PATH: /scripts/validate/changelog.sh
|
||||||
|
# VERSION: 01.00.00
|
||||||
|
# BRIEF: Validates CHANGELOG.md structure and version entries
|
||||||
|
# NOTE: Ensures changelog compliance with Keep a Changelog standard
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
json_escape() {
|
json_escape() {
|
||||||
|
|||||||
@@ -1,4 +1,38 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
|
#
|
||||||
|
# This file is part of a Moko Consulting project.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program (./LICENSE.md).
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# FILE INFORMATION
|
||||||
|
# ============================================================================
|
||||||
|
# DEFGROUP: Script.Validate
|
||||||
|
# INGROUP: Joomla.Language
|
||||||
|
# REPO: https://github.com/mokoconsulting-tech/moko-cassiopeia
|
||||||
|
# PATH: /scripts/validate/language_structure.sh
|
||||||
|
# VERSION: 01.00.00
|
||||||
|
# BRIEF: Validates Joomla language directory structure and INI files
|
||||||
|
# NOTE: Ensures proper language file organization
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
SRC_DIR="${SRC_DIR:-src}"
|
SRC_DIR="${SRC_DIR:-src}"
|
||||||
|
|||||||
@@ -1,4 +1,38 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
|
#
|
||||||
|
# This file is part of a Moko Consulting project.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program (./LICENSE.md).
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# FILE INFORMATION
|
||||||
|
# ============================================================================
|
||||||
|
# DEFGROUP: Script.Validate
|
||||||
|
# INGROUP: Licensing
|
||||||
|
# REPO: https://github.com/mokoconsulting-tech/moko-cassiopeia
|
||||||
|
# PATH: /scripts/validate/license_headers.sh
|
||||||
|
# VERSION: 01.00.00
|
||||||
|
# BRIEF: Checks that source files contain SPDX license identifiers
|
||||||
|
# NOTE: Ensures licensing compliance across codebase
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
SRC_DIR="${SRC_DIR:-src}"
|
SRC_DIR="${SRC_DIR:-src}"
|
||||||
|
|||||||
@@ -1,6 +1,43 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
|
#
|
||||||
|
# This file is part of a Moko Consulting project.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program (./LICENSE.md).
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# FILE INFORMATION
|
||||||
|
# ============================================================================
|
||||||
|
# DEFGROUP: Script.Validate
|
||||||
|
# INGROUP: Joomla.Manifest
|
||||||
|
# REPO: https://github.com/mokoconsulting-tech/moko-cassiopeia
|
||||||
|
# PATH: /scripts/validate/manifest.sh
|
||||||
|
# VERSION: 01.00.00
|
||||||
|
# BRIEF: Validates Joomla manifest XML structure and required fields
|
||||||
|
# NOTE: Ensures extension manifest compliance
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Input validation
|
||||||
|
SRC_DIR="${SRC_DIR:-src}"
|
||||||
|
|
||||||
log() { printf '%s\n' "$*"; }
|
log() { printf '%s\n' "$*"; }
|
||||||
|
|
||||||
fail() {
|
fail() {
|
||||||
@@ -8,10 +45,14 @@ fail() {
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
SRC_DIR="${SRC_DIR:-src}"
|
# Validate SRC_DIR
|
||||||
|
|
||||||
if [ ! -d "${SRC_DIR}" ]; then
|
if [ ! -d "${SRC_DIR}" ]; then
|
||||||
fail "${SRC_DIR} directory missing"
|
fail "${SRC_DIR} directory missing. Set SRC_DIR environment variable or ensure 'src' directory exists."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Validate required dependencies
|
||||||
|
if ! command -v python3 >/dev/null 2>&1; then
|
||||||
|
fail "python3 is required but not found. Please install Python 3."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Candidate discovery policy: prefer explicit known names, otherwise fall back to extension-root manifests.
|
# Candidate discovery policy: prefer explicit known names, otherwise fall back to extension-root manifests.
|
||||||
@@ -51,7 +92,23 @@ if [ "${#manifest_candidates[@]}" -eq 0 ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${#manifest_candidates[@]}" -eq 0 ]; then
|
if [ "${#manifest_candidates[@]}" -eq 0 ]; then
|
||||||
fail "No Joomla manifest XML found under ${SRC_DIR}"
|
{
|
||||||
|
echo "ERROR: No Joomla manifest XML found under ${SRC_DIR}" >&2
|
||||||
|
echo "" >&2
|
||||||
|
echo "Expected manifest file patterns:" >&2
|
||||||
|
echo " - Template: ${SRC_DIR}/templateDetails.xml" >&2
|
||||||
|
echo " - Package: ${SRC_DIR}/**/pkg_*.xml" >&2
|
||||||
|
echo " - Component: ${SRC_DIR}/**/com_*.xml" >&2
|
||||||
|
echo " - Module: ${SRC_DIR}/**/mod_*.xml" >&2
|
||||||
|
echo " - Plugin: ${SRC_DIR}/**/plg_*.xml" >&2
|
||||||
|
echo "" >&2
|
||||||
|
echo "Troubleshooting:" >&2
|
||||||
|
echo " 1. Verify the source directory exists: ls -la ${SRC_DIR}" >&2
|
||||||
|
echo " 2. Check for XML files: find ${SRC_DIR} -name '*.xml'" >&2
|
||||||
|
echo " 3. Ensure manifest contains <extension> root element" >&2
|
||||||
|
echo "" >&2
|
||||||
|
} >&2
|
||||||
|
fail "No manifest found"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# De-duplicate while preserving order.
|
# De-duplicate while preserving order.
|
||||||
@@ -74,11 +131,21 @@ manifest_candidates=("${unique_candidates[@]}")
|
|||||||
if [ "${#manifest_candidates[@]}" -gt 1 ]; then
|
if [ "${#manifest_candidates[@]}" -gt 1 ]; then
|
||||||
{
|
{
|
||||||
log "ERROR: Multiple manifest candidates detected. Resolve to exactly one primary manifest." >&2
|
log "ERROR: Multiple manifest candidates detected. Resolve to exactly one primary manifest." >&2
|
||||||
log "Candidates:" >&2
|
log "" >&2
|
||||||
|
log "Found ${#manifest_candidates[@]} candidates:" >&2
|
||||||
for c in "${manifest_candidates[@]}"; do
|
for c in "${manifest_candidates[@]}"; do
|
||||||
log "- ${c}" >&2
|
log " - ${c}" >&2
|
||||||
done
|
done
|
||||||
}
|
log "" >&2
|
||||||
|
log "Resolution options:" >&2
|
||||||
|
log " 1. Remove redundant manifest files" >&2
|
||||||
|
log " 2. Move extra manifests outside ${SRC_DIR}" >&2
|
||||||
|
log " 3. Rename non-primary manifests to not match patterns (templateDetails.xml, pkg_*.xml, etc.)" >&2
|
||||||
|
log "" >&2
|
||||||
|
log "For package extensions, only the top-level package manifest should be in ${SRC_DIR}." >&2
|
||||||
|
log "Child extension manifests should be in subdirectories." >&2
|
||||||
|
log "" >&2
|
||||||
|
} >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,38 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
|
#
|
||||||
|
# This file is part of a Moko Consulting project.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program (./LICENSE.md).
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# FILE INFORMATION
|
||||||
|
# ============================================================================
|
||||||
|
# DEFGROUP: Script.Validate
|
||||||
|
# INGROUP: Security
|
||||||
|
# REPO: https://github.com/mokoconsulting-tech/moko-cassiopeia
|
||||||
|
# PATH: /scripts/validate/no_secrets.sh
|
||||||
|
# VERSION: 01.00.00
|
||||||
|
# BRIEF: Scan for accidentally committed secrets and credentials
|
||||||
|
# NOTE: High-signal pattern detection to prevent credential exposure
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
SRC_DIR="${SRC_DIR:-src}"
|
SRC_DIR="${SRC_DIR:-src}"
|
||||||
|
|||||||
@@ -1,25 +1,77 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
|
#
|
||||||
|
# This file is part of a Moko Consulting project.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program (./LICENSE.md).
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# FILE INFORMATION
|
||||||
|
# ============================================================================
|
||||||
|
# DEFGROUP: Script.Validate
|
||||||
|
# INGROUP: Path.Normalization
|
||||||
|
# REPO: https://github.com/mokoconsulting-tech/moko-cassiopeia
|
||||||
|
# PATH: /scripts/validate/paths.sh
|
||||||
|
# VERSION: 01.00.00
|
||||||
|
# BRIEF: Detect Windows-style path separators (backslashes)
|
||||||
|
# NOTE: Ensures cross-platform path compatibility
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
# Detect Windows-style path literals (backslashes) in repository files.
|
# Detect Windows-style path literals (backslashes) in repository files.
|
||||||
# Uses git ls-files -z and searches file contents for a literal backslash.
|
# Uses git ls-files -z and searches file contents for a literal backslash.
|
||||||
|
|
||||||
hits=()
|
hits=()
|
||||||
|
hit_lines=()
|
||||||
|
|
||||||
while IFS= read -r -d '' f; do
|
while IFS= read -r -d '' f; do
|
||||||
# Skip common binary files by mime-type
|
# Skip common binary files by mime-type
|
||||||
if file --brief --mime-type "$f" | grep -qE '^(application|audio|image|video)/'; then
|
if file --brief --mime-type "$f" | grep -qE '^(application|audio|image|video)/'; then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
if grep -F $'\\' -- "$f" >/dev/null 2>&1; then
|
# Find lines with backslashes and collect details
|
||||||
|
if backslash_lines=$(grep -n -F $'\\' -- "$f" 2>/dev/null); then
|
||||||
hits+=("$f")
|
hits+=("$f")
|
||||||
|
hit_lines+=("$backslash_lines")
|
||||||
fi
|
fi
|
||||||
done < <(git ls-files -z)
|
done < <(git ls-files -z)
|
||||||
|
|
||||||
if [ "${#hits[@]}" -gt 0 ]; then
|
if [ "${#hits[@]}" -gt 0 ]; then
|
||||||
echo "ERROR: windows_path_literal_detected"
|
echo "ERROR: Windows-style path literals detected" >&2
|
||||||
for h in "${hits[@]}"; do
|
echo "" >&2
|
||||||
echo " - ${h}"
|
echo "Found backslashes in ${#hits[@]} file(s):" >&2
|
||||||
|
for i in "${!hits[@]}"; do
|
||||||
|
echo "" >&2
|
||||||
|
echo " File: ${hits[$i]}" >&2
|
||||||
|
echo " Lines with backslashes:" >&2
|
||||||
|
echo "${hit_lines[$i]}" | head -5 | sed 's/^/ /' >&2
|
||||||
|
if [ "$(echo "${hit_lines[$i]}" | wc -l)" -gt 5 ]; then
|
||||||
|
echo " ... and $(($(echo "${hit_lines[$i]}" | wc -l) - 5)) more" >&2
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
echo "" >&2
|
||||||
|
echo "To fix:" >&2
|
||||||
|
echo " 1. Run: ./scripts/fix/paths.sh" >&2
|
||||||
|
echo " 2. Or manually replace backslashes (\\) with forward slashes (/)" >&2
|
||||||
|
echo " 3. Ensure paths use POSIX separators for cross-platform compatibility" >&2
|
||||||
|
echo "" >&2
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,42 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
|
#
|
||||||
|
# This file is part of a Moko Consulting project.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program (./LICENSE.md).
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# FILE INFORMATION
|
||||||
|
# ============================================================================
|
||||||
|
# DEFGROUP: Script.Validate
|
||||||
|
# INGROUP: Code.Quality
|
||||||
|
# REPO: https://github.com/mokoconsulting-tech/moko-cassiopeia
|
||||||
|
# PATH: /scripts/validate/php_syntax.sh
|
||||||
|
# VERSION: 01.00.00
|
||||||
|
# BRIEF: Validates PHP syntax using php -l on all PHP files
|
||||||
|
# NOTE: Requires PHP CLI to be available
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Validation timeout (seconds) - prevents hanging on problematic files
|
||||||
|
TIMEOUT="${VALIDATION_TIMEOUT:-30}"
|
||||||
SRC_DIR="${SRC_DIR:-src}"
|
SRC_DIR="${SRC_DIR:-src}"
|
||||||
|
|
||||||
json_escape() {
|
json_escape() {
|
||||||
@@ -22,17 +58,53 @@ fi
|
|||||||
|
|
||||||
failed=0
|
failed=0
|
||||||
checked=0
|
checked=0
|
||||||
|
failed_files=()
|
||||||
|
failed_errors=()
|
||||||
|
|
||||||
while IFS= read -r -d '' f; do
|
while IFS= read -r -d '' f; do
|
||||||
checked=$((checked+1))
|
checked=$((checked+1))
|
||||||
if ! php -l "$f" >/dev/null; then
|
|
||||||
failed=1
|
# Capture actual error output
|
||||||
|
error_output=""
|
||||||
|
|
||||||
|
# Use timeout if available to prevent hangs
|
||||||
|
if command -v timeout >/dev/null 2>&1; then
|
||||||
|
if ! error_output=$(timeout "${TIMEOUT}" php -l "$f" 2>&1); then
|
||||||
|
failed=1
|
||||||
|
failed_files+=("$f")
|
||||||
|
failed_errors+=("$error_output")
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if ! error_output=$(php -l "$f" 2>&1); then
|
||||||
|
failed=1
|
||||||
|
failed_files+=("$f")
|
||||||
|
failed_errors+=("$error_output")
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
done < <(find "${SRC_DIR}" -type f -name '*.php' -print0)
|
done < <(find "${SRC_DIR}" -type f -name '*.php' -print0)
|
||||||
|
|
||||||
if [ "${failed}" -ne 0 ]; then
|
if [ "${failed}" -ne 0 ]; then
|
||||||
printf '{"status":"fail","error":"php_lint_failed","files_checked":%s}
|
echo "ERROR: PHP syntax validation failed" >&2
|
||||||
' "${checked}"
|
echo "Files checked: ${checked}" >&2
|
||||||
|
echo "Files with errors: ${#failed_files[@]}" >&2
|
||||||
|
echo "" >&2
|
||||||
|
echo "Failed files and errors:" >&2
|
||||||
|
for i in "${!failed_files[@]}"; do
|
||||||
|
echo " File: ${failed_files[$i]}" >&2
|
||||||
|
echo " Error: ${failed_errors[$i]}" >&2
|
||||||
|
echo "" >&2
|
||||||
|
done
|
||||||
|
echo "" >&2
|
||||||
|
echo "To fix: Review and correct the syntax errors in the files listed above." >&2
|
||||||
|
echo "Run 'php -l <filename>' on individual files for detailed error messages." >&2
|
||||||
|
{
|
||||||
|
printf '{"status":"fail","error":"php_lint_failed","files_checked":%s,"failed_count":%s,"failed_files":[' "${checked}" "${#failed_files[@]}"
|
||||||
|
for i in "${!failed_files[@]}"; do
|
||||||
|
printf '%s' "$(json_escape "${failed_files[$i]}")"
|
||||||
|
[ "$i" -lt $((${#failed_files[@]} - 1)) ] && printf ','
|
||||||
|
done
|
||||||
|
printf ']}\n'
|
||||||
|
}
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,38 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
|
#
|
||||||
|
# This file is part of a Moko Consulting project.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program (./LICENSE.md).
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# FILE INFORMATION
|
||||||
|
# ============================================================================
|
||||||
|
# DEFGROUP: Script.Validate
|
||||||
|
# INGROUP: Code.Quality
|
||||||
|
# REPO: https://github.com/mokoconsulting-tech/moko-cassiopeia
|
||||||
|
# PATH: /scripts/validate/tabs.sh
|
||||||
|
# VERSION: 01.00.00
|
||||||
|
# BRIEF: Detect TAB characters in YAML files where they are not allowed
|
||||||
|
# NOTE: YAML specification forbids tab characters
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
# Detect TAB characters in source files tracked by Git. Uses careful
|
# Detect TAB characters in source files tracked by Git. Uses careful
|
||||||
@@ -14,15 +48,39 @@ if [ -z "${files}" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
bad=0
|
bad=0
|
||||||
|
bad_files=()
|
||||||
|
bad_lines=()
|
||||||
|
|
||||||
while IFS= read -r f; do
|
while IFS= read -r f; do
|
||||||
if grep -n $'\t' -- "$f" >/dev/null 2>&1; then
|
# Find lines with tabs and store them
|
||||||
echo "TAB found in $f"
|
if tab_lines=$(grep -n $'\t' -- "$f" 2>/dev/null); then
|
||||||
|
echo "TAB found in $f" >&2
|
||||||
|
echo " Lines with tabs:" >&2
|
||||||
|
echo "$tab_lines" | head -5 | sed 's/^/ /' >&2
|
||||||
|
if [ "$(echo "$tab_lines" | wc -l)" -gt 5 ]; then
|
||||||
|
echo " ... and $(($(echo "$tab_lines" | wc -l) - 5)) more" >&2
|
||||||
|
fi
|
||||||
|
echo "" >&2
|
||||||
bad=1
|
bad=1
|
||||||
|
bad_files+=("$f")
|
||||||
fi
|
fi
|
||||||
done <<< "${files}"
|
done <<< "${files}"
|
||||||
|
|
||||||
if [ "${bad}" -ne 0 ]; then
|
if [ "${bad}" -ne 0 ]; then
|
||||||
|
echo "" >&2
|
||||||
echo "ERROR: Tabs found in repository files" >&2
|
echo "ERROR: Tabs found in repository files" >&2
|
||||||
|
echo "" >&2
|
||||||
|
echo "YAML specification forbids tab characters." >&2
|
||||||
|
echo "Found tabs in ${#bad_files[@]} file(s):" >&2
|
||||||
|
for f in "${bad_files[@]}"; do
|
||||||
|
echo " - $f" >&2
|
||||||
|
done
|
||||||
|
echo "" >&2
|
||||||
|
echo "To fix:" >&2
|
||||||
|
echo " 1. Run: ./scripts/fix/tabs.sh" >&2
|
||||||
|
echo " 2. Or manually replace tabs with spaces in your editor" >&2
|
||||||
|
echo " 3. Configure your editor to use spaces (not tabs) for YAML files" >&2
|
||||||
|
echo "" >&2
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,38 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
|
#
|
||||||
|
# This file is part of a Moko Consulting project.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program (./LICENSE.md).
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# FILE INFORMATION
|
||||||
|
# ============================================================================
|
||||||
|
# DEFGROUP: Script.Validate
|
||||||
|
# INGROUP: Version.Management
|
||||||
|
# REPO: https://github.com/mokoconsulting-tech/moko-cassiopeia
|
||||||
|
# PATH: /scripts/validate/version_alignment.sh
|
||||||
|
# VERSION: 01.00.00
|
||||||
|
# BRIEF: Checks that manifest version is documented in CHANGELOG.md
|
||||||
|
# NOTE: Ensures version consistency across repository
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
# Validate that the package/manifest version is present in CHANGELOG.md
|
# Validate that the package/manifest version is present in CHANGELOG.md
|
||||||
|
|||||||
@@ -1,5 +1,38 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
|
#
|
||||||
|
# This file is part of a Moko Consulting project.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program (./LICENSE.md).
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# FILE INFORMATION
|
||||||
|
# ============================================================================
|
||||||
|
# DEFGROUP: Script.Validate
|
||||||
|
# INGROUP: XML.Validation
|
||||||
|
# REPO: https://github.com/mokoconsulting-tech/moko-cassiopeia
|
||||||
|
# PATH: /scripts/validate/xml_wellformed.sh
|
||||||
|
# VERSION: 01.00.00
|
||||||
|
# BRIEF: Validates that all XML files are well-formed
|
||||||
|
# NOTE: Uses Python ElementTree for portable XML parsing
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
SRC_DIR="${SRC_DIR:-src}"
|
SRC_DIR="${SRC_DIR:-src}"
|
||||||
|
|||||||
Reference in New Issue
Block a user