This directory contains GitHub Actions workflows for automated CI/CD tasks.
A reusable composite action that sets up PHP and installs Composer dependencies with intelligent caching.
Benefits:
- Reduces Composer install time from 8-12 seconds to 2-4 seconds (with cache hit)
- Consistent PHP and Composer setup across all workflows
- Centralized cache management
Usage:
- name: Setup PHP with Composer
uses: ./.github/actions/setup-php-composer
with:
php-version: '8.2' # Optional, defaults to 8.2
php-extensions: 'mbstring, xml, json' # Optional
composer-flags: '--no-dev --optimize-autoloader' # OptionalUsed by:
phpunit.yml- Test executionphpstan.yml- Static analysispint.yml- Code formattingcomposer-update.yml- Dependency updatesyarn-update.yml- Frontend dependency updatesquickstart.yml- Smoke tests
Note: release.yml uses manual Composer caching (not this composite action) due to its custom production build flags (--no-dev).
Trigger: Automatically runs on every push to the master branch
Purpose: Creates a production-ready release package of InvoicePlane v2 and publishes it as a GitHub Release
What it does:
- Downloads translations from Crowdin - Retrieves the latest translations
- Builds frontend assets - Runs
yarn install --frozen-lockfile && yarn build - Installs PHP dependencies - Runs
composer install --no-devfor production - Cleans up node_modules - Removes Node.js dependencies
- Optimizes vendor directory - Removes unnecessary files (tests, docs, etc.)
- Creates release archive - Packages everything into a timestamped ZIP file
- Generates version tag - Creates a new version tag (alpha/beta/stable)
- Creates GitHub Release - Publishes release with changelog and artifacts
Release Types:
The workflow supports configurable release types (set in workflow file):
alpha- Pre-release versions (increments patch, adds -alpha suffix)beta- Beta versions (increments patch, adds -beta suffix)stable- Stable releases (increments minor version)
To change the release type, edit the RELEASE_TYPE environment variable at the top of release.yml.
Versioning:
The workflow automatically:
- Detects the latest tag (or starts from v0.0.0)
- Increments version based on release type
- Creates a new tag (e.g., v0.1.0-alpha, v0.2.0-beta, v1.0.0)
- Generates release notes showing changes since the previous tag
Security:
The workflow uses minimal permissions:
contents: write- Required for creating releases and tagsactions: write- Required for uploading workflow artifacts
Required Secrets:
Before using this workflow, you need to configure these GitHub secrets:
CROWDIN_PROJECT_ID- Your Crowdin project IDCROWDIN_PERSONAL_TOKEN- Your Crowdin personal access token
To add these secrets:
- Go to your repository Settings
- Navigate to Secrets and variables → Actions
- Click "New repository secret"
- Add each secret with its corresponding value
Crowdin Setup:
To get your Crowdin credentials:
- Log in to Crowdin
- Navigate to your InvoicePlane project
- Go to Settings → API
- Generate a Personal Access Token
- Copy your Project ID from the project settings
Accessing Releases:
After the workflow runs:
- Go to the Releases section of your repository
- Find the latest release (e.g., "Release v0.1.0-alpha")
- Download the ZIP file and checksums from the release assets
- Review the automated changelog
Artifacts are also available in the Actions tab for 90 days.
Trigger:
- Scheduled: Weekly on Mondays at 9:00 AM UTC
- Manual dispatch with update type selection
Purpose: Automates Composer (PHP) dependency updates with security checks
What it does:
- Runs security audit - Checks for known vulnerabilities
- Updates dependencies - Based on selected update type
- Runs smoke tests - Fast verification after updates (if changes detected)
- Creates pull request - Automated PR with update details
Update Types:
security-patch- Security and patch updates (default for scheduled runs)patch-minor- Patch and minor version updatesall-dependencies- All updates including major versions withcomposer bump
Smoke Tests:
After dependencies are updated, the workflow automatically runs smoke tests to verify core functionality:
- Only runs if
composer.lockhas changes - Uses
phpunit.smoke.xmlconfiguration - Executes tests marked with
#[Group('smoke')] - Continues even if tests fail (with
continue-on-error: true) - Typically completes in 10-30 seconds
Required Secrets:
This workflow requires a Personal Access Token (PAT) to create pull requests:
PAT_TOKEN- A GitHub Personal Access Token withrepoandworkflowscopes
To create and configure the PAT:
- Go to GitHub Settings > Developer settings > Personal access tokens (classic)
- Click "Generate new token (classic)"
- Give it a descriptive name like "InvoicePlane Automation"
- Select the
repoandworkflowscopes - Generate and copy the token
- Go to your repository Settings > Secrets and variables > Actions
- Click "New repository secret"
- Name:
PAT_TOKEN, Value: paste your token - Click "Add secret"
Why is a PAT required?
The default GITHUB_TOKEN has restricted permissions and cannot create pull requests that trigger other workflows (like CI tests). This is a GitHub security measure. Using a PAT with appropriate scopes allows the workflow to create PRs that will trigger other workflows.
Required Permissions:
contents: write- For creating branches and commitspull-requests: write- For creating pull requests
Trigger:
- Scheduled: Weekly on Mondays at 10:00 AM UTC
- Manual dispatch with update type selection
Purpose: Automates Yarn (JavaScript) dependency updates with security checks
What it does:
- Runs security audit - Checks for known vulnerabilities
- Updates dependencies - Based on selected update type
- Builds assets - Verifies frontend builds correctly
- Creates pull request - Automated PR with update details
Update Types:
security-only- Only security fixes (default for scheduled runs)patch-minor- Patch and minor version updatesall-dependencies- All updates including major versions
Required Secrets:
This workflow requires a Personal Access Token (PAT) to create pull requests:
PAT_TOKEN- A GitHub Personal Access Token withrepoandworkflowscopes
To create and configure the PAT:
- Go to GitHub Settings > Developer settings > Personal access tokens (classic)
- Click "Generate new token (classic)"
- Give it a descriptive name like "InvoicePlane Automation"
- Select the
repoandworkflowscopes - Generate and copy the token
- Go to your repository Settings > Secrets and variables > Actions
- Click "New repository secret"
- Name:
PAT_TOKEN, Value: paste your token - Click "Add secret"
Why is a PAT required?
The default GITHUB_TOKEN has restricted permissions and cannot create pull requests that trigger other workflows (like CI tests). This is a GitHub security measure. Using a PAT with appropriate scopes allows the workflow to create PRs that will trigger other workflows.
Required Permissions:
contents: write- For creating branches and commitspull-requests: write- For creating pull requests
Trigger: Manual dispatch only
Runs the PHPUnit test suite against a MySQL database.
Trigger:
- Automatically on pull requests targeting
masterordevelopbranches - Manual dispatch
Purpose: Ensures consistent PHP code style across the codebase using Laravel Pint (PSR-12 standard)
What it does:
- Checks out the PR branch - Gets the latest code from the pull request
- Sets up PHP environment - Installs PHP 8.2 with required extensions
- Installs dependencies - Runs
composer install - Runs Laravel Pint - Automatically fixes code style issues
- Commits changes - Pushes formatted code back to the PR (if changes were made)
- Reports parse errors - Identifies files with syntax errors that couldn't be formatted
Best Practices:
When to use Pint:
- Before committing - Run
vendor/bin/pintlocally before pushing code - On every PR - The workflow automatically runs on PRs to master/develop
- Manual cleanup - Use workflow_dispatch to format the entire codebase
- After merging - Run manually if formatting conflicts occur
Local Development:
# Format all files
vendor/bin/pint
# Format specific files/directories
vendor/bin/pint app/Models
vendor/bin/pint Modules/Invoices
# Check without modifying files (dry-run)
vendor/bin/pint --test
# See what changes Pint would make
vendor/bin/pint --test -vPre-commit Hook (Recommended):
To automatically format code before each commit, add this to .git/hooks/pre-commit:
#!/bin/sh
# Run Laravel Pint on staged PHP files
php vendor/bin/pint $(git diff --cached --name-only --diff-filter=ACM | grep '\.php$')Make it executable: chmod +x .git/hooks/pre-commit
IDE Integration:
- PHPStorm/IntelliJ: Configure as External Tool or File Watcher
- VS Code: Install "Laravel Pint" extension for automatic formatting
- Sublime Text: Use "Laravel Pint" package
Configuration:
Pint uses the configuration in pint.json which follows PSR-12 with custom rules:
- Short array syntax
- Single quotes for strings
- Aligned operators (=, =>)
- Ordered imports and class elements
- Strict null coalescing
- And more...
See pint.json for complete rule set.
Handling Parse Errors:
If Pint reports parse errors:
- Review the workflow output to identify files with syntax errors (marked with
!) - Fix the syntax errors manually
- Re-run Pint locally or via the workflow
- Formatted files are still committed even if some files have errors
Why Run on PRs:
Running Pint automatically on PRs ensures:
- ✅ Consistent code style across all contributions
- ✅ No style-related review comments needed
- ✅ Cleaner git history (style fixes separate from logic changes)
- ✅ Reduced merge conflicts related to formatting
- ✅ Faster code reviews (focus on logic, not style)
Workflow Permissions:
contents: write- Required to commit and push formatting changes
Note: The workflow only runs on PRs targeting master or develop branches to avoid unnecessary runs on feature branches. You can always trigger it manually for any branch using workflow_dispatch.
Trigger: Manual dispatch only
Purpose: Runs static analysis on PHP code to detect type errors, bugs, and potential issues before runtime
What it does:
- Runs PHPStan analysis - Analyzes code with JSON output format
- Parses and formats results - Converts verbose JSON into actionable markdown
- Groups errors by category - Type errors, method errors, property errors, etc.
- Generates checklists - Creates ready-to-use task lists for fixing errors
- Uploads artifacts - Saves JSON and markdown reports for later review
- Comments on PRs (if triggered from PR) - Posts formatted report as PR comment
Analysis Features:
The workflow includes smart error formatting:
- 🔢 Type Errors - Type mismatches and expectations
- 🔧 Method Errors - Undefined or incorrect method calls
- 📦 Property Errors - Property access issues
- ↩️ Return Type Errors - Incorrect return types
⚠️ Other Errors - Miscellaneous issues
Local Development:
# Run PHPStan with standard output
vendor/bin/phpstan analyse --memory-limit=1G
# Generate JSON output for parsing
vendor/bin/phpstan analyse --error-format=json > phpstan.json
# Parse results into actionable format
php .github/scripts/parse-phpstan-results.php phpstan.json > phpstan-report.md
# View the formatted report
cat phpstan-report.mdBest Practices:
When to run PHPStan:
- Before major refactoring - Identify potential issues early
- After adding new features - Ensure type safety
- When upgrading dependencies - Catch compatibility issues
- Before releases - Final quality check
Working with Results:
The parser script generates three sections:
- Error Summary - Quick overview by category
- Detailed Errors - Grouped by file with line numbers
- Actionable Checklist - Track fixes systematically
Integration with Copilot:
The formatted output is optimized for Copilot:
- JSON format provides precise, machine-readable data
- Trimmed context focuses on actionable items
- Explicit categorization aids understanding
- Checklist format enables task tracking
Workflow:
- Generate JSON:
vendor/bin/phpstan analyse --error-format=json > phpstan.json - Parse results:
php .github/scripts/parse-phpstan-results.php phpstan.json - Feed to Copilot: Copy formatted report for automated suggestions
- Fix errors: Use checklist to track progress systematically
Configuration:
PHPStan configuration is in phpstan.neon:
- Level 3 analysis (balanced strictness)
- Analyzes all
Modules/directory - Excludes HTTP controllers (autogenerated)
- Custom ignore patterns for framework-specific patterns
Baseline Generation:
If you need to accept existing errors and focus on new issues:
vendor/bin/phpstan analyse --generate-baselineThis creates phpstan-baseline.neon with current errors. Uncomment the baseline include in phpstan.neon.
Script Details:
The parsing script (.github/scripts/parse-phpstan-results.php):
- Categorizes errors by type
- Trims verbose messages for readability
- Groups errors by file
- Generates markdown checklists
- Optimized for GitHub PR comments
See .github/scripts/README.md for detailed script documentation.
Trigger: Manual dispatch only
Tests Docker Compose configuration.
Trigger: Manual dispatch only
Purpose: Provides a complete application setup workflow with granular error handling and selective step execution for debugging
What it does:
- Yarn Install - Installs JavaScript dependencies
- Composer Install - Installs PHP dependencies
- Environment Setup - Copies
.env.exampleto.env - Key Generation - Runs
php artisan key:generate - Database Migration - Runs
php artisan migrate --force - Database Seeding - Runs
php artisan db:seed
Key Features:
Selective Step Execution:
- Each step can be individually enabled or disabled via workflow inputs
- Allows running only specific steps for debugging
- Default: All steps enabled
Error Handling:
- Uses
set +eto continue execution after errors - Each step captures its exit code
- Errors are logged to a central error report
- Workflow continues even if steps fail
- Final step reports all errors in a consolidated summary
Error Reporting:
- Errors logged with step name and exit code
- Detailed error report at workflow end
- GitHub Actions summary shows pass/fail status for each step
- Individual step logs preserved for debugging
Usage:
To run the full setup:
- Go to Actions tab
- Select Setup & Install with Error Handling
- Click Run workflow
- Leave all options as "true" (default)
- Click Run workflow
To debug specific steps:
- Go to Actions tab
- Select Setup & Install with Error Handling
- Click Run workflow
- Set unwanted steps to "false"
- Click Run workflow
Example Scenarios:
Full Setup:
- All inputs set to
true(default) - Runs complete installation from scratch
Debug Seeding Only:
run_seed:true- All others:
false - Useful for testing seeder changes
Debug Migration + Seeding:
run_migrate:truerun_seed:true- All others:
false - Useful for testing database setup
Infrastructure:
- MariaDB 10.6 service container
- PHP 8.4 with required extensions
- Node.js 22 with Yarn caching
Known Issues Fixed:
- ✅ AddressFactory faker instance issue fixed (now uses
$this->fakerconsistently) - ✅ Yarn EISDIR errors handled gracefully
- ✅ All errors collected and reported at the end
Trigger: Manual dispatch only
Provides a quick setup for development environments.
Trigger:
- Scheduled: Weekly on Sundays at 2:00 AM UTC
- Manual dispatch with action type selection
Purpose: Automates translation synchronization with Crowdin
What it does:
- Uploads source files - Pushes English translation files to Crowdin
- Downloads translations - Retrieves translated files from Crowdin
- Creates pull request - Automated PR with translation updates
Action Types:
upload-sources- Upload source translation files onlydownload-translations- Download translated files only (default)sync-bidirectional- Both upload and download
Required Secrets:
This workflow requires a Personal Access Token (PAT) to create pull requests:
PAT_TOKEN- A GitHub Personal Access Token withrepoandworkflowscopesCROWDIN_PROJECT_ID- Your Crowdin project IDCROWDIN_PERSONAL_TOKEN- Your Crowdin personal access token
To create and configure the PAT:
- Go to GitHub Settings > Developer settings > Personal access tokens (classic)
- Click "Generate new token (classic)"
- Give it a descriptive name like "InvoicePlane Automation"
- Select the
repoandworkflowscopes - Generate and copy the token
- Go to your repository Settings > Secrets and variables > Actions
- Click "New repository secret"
- Name:
PAT_TOKEN, Value: paste your token - Click "Add secret"
Why is a PAT required?
The default GITHUB_TOKEN has restricted permissions and cannot create pull requests that trigger other workflows (like CI tests). This is a GitHub security measure. Using a PAT with appropriate scopes allows the workflow to create PRs that will trigger other workflows.
Required Permissions:
contents: write- For creating branches and commitspull-requests: write- For creating pull requests
InvoicePlane v2 uses GitHub Dependabot for automated dependency updates. Configuration is in .github/dependabot.yml.
What Dependabot monitors:
- Composer (PHP dependencies) - Weekly updates on Mondays
- npm/Yarn (JavaScript dependencies) - Weekly updates on Mondays
- GitHub Actions - Monthly updates
How it works:
- Dependabot scans for outdated or vulnerable dependencies
- Creates pull requests for updates
- Groups updates by type (security, patch, minor)
- Automatically labels PRs for easy filtering
Managing Dependabot PRs:
- Review the changelog and breaking changes
- Run tests locally if needed
- Merge when ready or close if not needed
- Use
@dependabot rebaseto rebase the PR
See MAINTENANCE.md for detailed dependency management guidelines.
Use the manual workflows when you need immediate updates:
- Go to Actions tab
- Select Composer Update or Yarn Update
- Click Run workflow
- Select update type
- Wait for automated PR
The release workflow aggressively cleans the vendor directory to minimize file size:
- Removes all test directories (
tests,Tests,test,Test) - Removes all documentation (
docs,doc,*.md,*.txt) - Removes all Git metadata (
.git,.gitignore,.gitattributes) - Removes build files (
composer.json,composer.lock,phpunit.xml, etc.) - Removes code quality files (
.php_cs,phpstan.neon, etc.)
This typically reduces the vendor directory size by 40-60%.
The following files and directories are excluded from the release archive:
- Development files:
.github/*,tests/*,README.md - Configuration files:
phpunit.xml,phpstan.neon,pint.json,rector.php - Build tools:
package.json,yarn.lock,vite.config.js,tailwind.config.js - Docker files:
docker-compose.yml - Environment files:
.env* - Storage:
storage/logs/*,storage/framework/cache/* - Node modules:
node_modules/*(already removed in cleanup step)
If the Crowdin step fails, check:
- Secrets are correctly configured
- Your Crowdin personal token has not expired
- The project ID is correct
- Your Crowdin project is properly configured
If the frontend build fails:
- Ensure
package.jsonis up to date - Check for syntax errors in Vite/Tailwind config
- Verify all dependencies are correctly specified
If Composer installation fails:
- Check
composer.jsonfor syntax errors - Ensure all required PHP extensions are available
- Verify package versions are compatible
Edit line 49 in release.yml:
php-version: '8.3' # Using 8.3 for latest features; composer.json requires ^8.2Edit line 36 in release.yml:
node-version: '20' # Change to your desired versionEdit line 121 in release.yml:
retention-days: 90 # Change to your desired retention period (1-90 days)Add or remove exclusions in the "Create release zip" step (lines 86-110).
- Test locally first - Before relying on the workflow, test the build process locally
- Monitor workflow runs - Check the Actions tab regularly for failures
- Keep secrets secure - Never commit secrets to the repository
- Update dependencies - Keep GitHub Actions and dependencies up to date
- Tag releases - Use semantic versioning for production releases
For issues or questions about these workflows:
- Create an issue in the repository
- Join the Community Forums
- Visit the Discord server