Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions .github/workflows/static-analysis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
name: Static Analysis

on:
push:
branches: [ main, master, develop ]
pull_request:
branches: [ main, master, develop ]

jobs:
phpstan:
name: PHPStan Analysis
runs-on: ubuntu-latest

strategy:
matrix:
include:
# Laravel 10 with Larastan 2.x
- php-version: '8.2'
laravel-version: '10.*'
larastan-version: '^2.0'
- php-version: '8.3'
laravel-version: '10.*'
larastan-version: '^2.0'

# Laravel 11 with Larastan 2.x
- php-version: '8.2'
laravel-version: '11.*'
larastan-version: '^2.0'
- php-version: '8.3'
laravel-version: '11.*'
larastan-version: '^2.0'

# Laravel 12 with Larastan 3.x (when available)
- php-version: '8.2'
laravel-version: '12.*'
larastan-version: '^3.1'
- php-version: '8.3'
laravel-version: '12.*'
larastan-version: '^3.1'

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick
coverage: none

- name: Cache Composer packages
id: composer-cache
uses: actions/cache@v3
with:
path: vendor
key: ${{ runner.os }}-php-${{ matrix.php-version }}-laravel-${{ matrix.laravel-version }}-larastan-${{ matrix.larastan-version }}-${{ hashFiles('**/composer.json') }}
restore-keys: |
${{ runner.os }}-php-${{ matrix.php-version }}-laravel-${{ matrix.laravel-version }}-

- name: Install dependencies
run: |
composer require "illuminate/support:${{ matrix.laravel-version }}" "larastan/larastan:${{ matrix.larastan-version }}" --no-interaction --no-update
composer install --prefer-dist --no-interaction

- name: Run PHPStan
run: composer run phpstan

code-quality:
name: Code Quality Checks
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick
coverage: none

- name: Install dependencies (with Laravel 11 and Larastan 2.x for compatibility)
run: |
composer require "illuminate/support:^11.0" "larastan/larastan:^2.0" --no-interaction --no-update
composer install --prefer-dist --no-interaction

- name: Check code style (if PHP CS Fixer is available)
run: |
if [ -f vendor/bin/php-cs-fixer ]; then
vendor/bin/php-cs-fixer fix --dry-run --diff
else
echo "PHP CS Fixer not installed, skipping code style check"
fi
continue-on-error: true

- name: Run static analysis
run: composer run phpstan
16 changes: 16 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
composer.phar
composer.lock
/vendor/

# PHPStan
phpstan-baseline.neon
.phpunit.result.cache

# Development files (keep phpstan-bootstrap.php in repo for static analysis)

# IDE
.vscode/
.idea/
*.swp
*.swo

# OS
.DS_Store
Thumbs.db
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,18 @@ Invalid dashboard or question ID.

### Message seems corrupt or manipulated.
Invalid secret key.

## Development

This package uses [Larastan](https://github.com/larastan/larastan) for static analysis at level 9 to ensure code quality.

### Running Static Analysis
```bash
composer phpstan
```

### Requirements
- PHP 8.2+
- Laravel 8.0+ (supports up to Laravel 12.x)

For detailed static analysis information, see [STATIC_ANALYSIS.md](STATIC_ANALYSIS.md).
144 changes: 144 additions & 0 deletions STATIC_ANALYSIS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# Static Analysis with Larastan

This package uses [Larastan](https://github.com/larastan/larastan) (PHPStan for Laravel) for static analysis to ensure code quality and catch potential bugs before runtime.

## Configuration

The static analysis is configured at **level 9** (the highest level) in `phpstan.neon` for maximum code quality assurance.

### Version Compatibility

Due to Larastan's version constraints, different Laravel versions require different Larastan versions:

- **Laravel 8-11**: Uses Larastan `^2.0`
- **Laravel 12**: Uses Larastan `^3.1` (when available)

The package automatically handles these constraints in `composer.json`.

### Key Features

- **Level 9 Analysis**: The strictest level of static analysis
- **Laravel Integration**: Full Laravel framework support through Larastan
- **Type Safety**: Comprehensive type checking and validation
- **Generic Types**: Support for generic collections and arrays
- **Uninitialized Properties**: Detection of uninitialized class properties
- **Return Type Analysis**: Verification of method return types

## Running Static Analysis

### Local Development

```bash
# Run static analysis
composer phpstan

# Alternative commands
composer analyse
composer test-static
composer check

# Clear PHPStan cache
composer phpstan-clear

# Generate baseline (if needed)
composer phpstan-baseline
```

### Memory Usage

The analysis runs with 1GB memory limit by default. If you encounter memory issues:

```bash
# Increase memory limit
vendor/bin/phpstan analyse --memory-limit=2G
```

## Continuous Integration

Static analysis runs automatically on:
- Push to main/master/develop branches
- Pull requests to main/master/develop branches
- Multiple PHP versions (8.2, 8.3)
- Multiple Laravel versions with compatible Larastan versions:
- Laravel 10.x + Larastan 2.x
- Laravel 11.x + Larastan 2.x
- Laravel 12.x + Larastan 3.x

## Configuration Details

### Analysis Paths
- `src/` - Main source code
- `config/` - Configuration files
- `routes/` - Route definitions

### Excluded Paths
- `vendor/` - Third-party packages
- `storage/` - Laravel storage directory
- `bootstrap/cache/` - Laravel cache files

### Bootstrap Files
- `phpstan-bootstrap.php` - Custom Laravel helper function definitions for static analysis

### Configuration Features
- **Level 9 Analysis**: Maximum strictness for type checking
- **Laravel Integration**: Full framework support via Larastan extension
- **Custom Bootstrap**: Laravel helper function definitions
- **Strategic Ignores**: Allows Laravel-specific patterns while maintaining strictness

### Laravel-Specific Handling
- Ignores Laravel helper functions (`config()`, `view()`, `app()`)
- Handles Laravel facades and service container
- Supports Blade component analysis

## Benefits

1. **Early Bug Detection**: Catch type errors before runtime
2. **Better IDE Support**: Enhanced autocompletion and refactoring
3. **Documentation**: Type hints serve as inline documentation
4. **Refactoring Safety**: Confident code changes with type checking
5. **Team Consistency**: Enforced coding standards across the team

## Troubleshooting

### Common Issues

1. **Memory Errors**: Increase memory limit in composer scripts
2. **False Positives**: Add specific ignores to `phpstan.neon`
3. **Missing Types**: Add proper PHPDoc annotations
4. **Configuration Errors**: Ensure only valid PHPStan parameters are used
5. **Version Conflicts**: Ensure Laravel and Larastan versions are compatible:
```bash
# For Laravel 10-11
composer require --dev "larastan/larastan:^2.0"

# For Laravel 12
composer require --dev "larastan/larastan:^3.1"
```

### Baseline Usage

If you need to temporarily ignore existing issues:

```bash
composer phpstan-baseline
```

This creates a `phpstan-baseline.neon` file with current issues that will be ignored in future runs.

## Best Practices

1. **Run Before Commits**: Always run static analysis before committing
2. **Fix Issues Promptly**: Don't let static analysis issues accumulate
3. **Use Strict Types**: Leverage PHP 8.2+ features for better type safety
4. **Document Complex Types**: Use PHPDoc for complex generic types
5. **Review Ignores**: Regularly review and remove unnecessary ignores

## Integration with IDEs

Most modern IDEs support PHPStan integration:

- **PhpStorm**: Built-in support with PHPStan plugin
- **VS Code**: Use the PHPStan extension
- **Vim/Neovim**: Various PHPStan plugins available

This ensures real-time feedback while coding, not just during CI/CD.
46 changes: 46 additions & 0 deletions check-larastan-compatibility.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/bin/bash

# Script to check and install compatible Larastan version
# Usage: ./check-larastan-compatibility.sh

echo "🔍 Checking Laravel and Larastan compatibility..."

# Check if composer.json exists
if [ ! -f "composer.json" ]; then
echo "❌ composer.json not found in current directory"
exit 1
fi

# Extract Laravel version from composer.json
LARAVEL_VERSION=$(php -r "
\$composer = json_decode(file_get_contents('composer.json'), true);
\$illuminate = \$composer['require']['illuminate/support'] ?? '';
echo \$illuminate;
")

if [ -z "$LARAVEL_VERSION" ]; then
echo "❌ Could not determine Laravel version from composer.json"
exit 1
fi

echo "📦 Found illuminate/support constraint: $LARAVEL_VERSION"

# Determine appropriate Larastan version
if [[ $LARAVEL_VERSION == *"12."* ]]; then
LARASTAN_VERSION="^3.1"
echo "✅ Laravel 12 detected - recommending Larastan $LARASTAN_VERSION"
elif [[ $LARAVEL_VERSION == *"11."* ]] || [[ $LARAVEL_VERSION == *"10."* ]] || [[ $LARAVEL_VERSION == *"9."* ]] || [[ $LARAVEL_VERSION == *"8."* ]]; then
LARASTAN_VERSION="^2.0"
echo "✅ Laravel 8-11 detected - recommending Larastan $LARASTAN_VERSION"
else
echo "⚠️ Could not determine appropriate Larastan version for Laravel constraint: $LARAVEL_VERSION"
echo " Please check manually at: https://github.com/larastan/larastan#compatibility"
exit 1
fi

echo ""
echo "🚀 To install the compatible version, run:"
echo " composer require --dev \"larastan/larastan:$LARASTAN_VERSION\""
echo ""
echo "📝 Then run static analysis with:"
echo " composer phpstan"
21 changes: 17 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
}
],
"require": {
"php": "^8.0",
"illuminate/support": "^8.0|^9.0",
"lcobucci/jwt": "^4.1"
"php": "^8.2",
"illuminate/support": "12.*",
"lcobucci/jwt": "^4.1|^5.0"
},
"autoload": {
"psr-4": {
Expand All @@ -31,6 +31,19 @@
]
}
},
"scripts": {
"phpstan": "phpstan analyse",
"phpstan-baseline": "phpstan analyse --generate-baseline --memory-limit=1G",
"phpstan-clear": "phpstan clear-result-cache",
"test-static": "@phpstan",
"analyse": "@phpstan",
"check": [
"@phpstan"
]
},
"minimum-stability": "dev",
"prefer-stable": true
"prefer-stable": true,
"require-dev": {
"larastan/larastan": "^3.7"
}
}
Loading
Loading