Skip to content
Merged
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
76 changes: 76 additions & 0 deletions .github/workflows/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: Bug Report
description: Something is broken or behaving unexpectedly
labels: ["bug", "needs-triage"]
body:
- type: markdown
attributes:
value: |
Thank you for taking the time to report a bug. Please fill out the sections below as completely as possible.

- type: textarea
id: description
attributes:
label: Describe the bug
description: A clear and concise description of what the bug is.
validations:
required: true

- type: textarea
id: reproduce
attributes:
label: Steps to reproduce
description: Minimal code or CLI steps to reproduce the behavior.
placeholder: |
```php
$input = (new TextInput('Name'))->run();
```
validations:
required: true

- type: textarea
id: expected
attributes:
label: Expected behavior
description: What you expected to happen.
validations:
required: true

- type: textarea
id: actual
attributes:
label: Actual behavior
description: What actually happened. Include any error messages or terminal output.
validations:
required: true

- type: input
id: php-version
attributes:
label: PHP version
placeholder: "e.g. 8.3.2"
validations:
required: true

- type: input
id: os
attributes:
label: Operating system
placeholder: "e.g. Ubuntu 22.04, macOS 14, Windows 11"
validations:
required: true

- type: input
id: terminal
attributes:
label: Terminal / shell
placeholder: "e.g. iTerm2 / zsh, Windows Terminal / PowerShell"
validations:
required: false

- type: input
id: package-version
attributes:
label: php-io-cli version
placeholder: "e.g. 1.0.0"
validations:
required: true
169 changes: 169 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
name: CI

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

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
# ──────────────────────────────────────────────────────────────────
# Static Analysis — PHPStan
# ──────────────────────────────────────────────────────────────────
phpstan:
name: "PHPStan (level 8)"
runs-on: ubuntu-latest

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

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: "8.2"
coverage: none
tools: composer:v2

- name: Get Composer cache directory
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

- name: Cache Composer dependencies
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: composer-${{ runner.os }}-php8.2-${{ hashFiles('**/composer.lock') }}
restore-keys: composer-${{ runner.os }}-php8.2-

- name: Install dependencies
run: composer install --no-interaction --prefer-dist --no-progress

- name: Run PHPStan
run: vendor/bin/phpstan analyse --error-format=github

# ──────────────────────────────────────────────────────────────────
# Test Matrix — PHP 8.2, 8.3, 8.4 × latest deps / lowest deps
# ──────────────────────────────────────────────────────────────────
tests:
name: "PHPUnit (${{ matrix.php }}, ${{ matrix.deps }})"
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
php: [ "8.2", "8.3", "8.4" ]
deps: [ "latest", "lowest" ]
exclude:
# lowest deps with bleeding-edge PHP is noisy — skip it
- php: "8.4"
deps: "lowest"

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

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: mbstring, pcntl, posix
coverage: ${{ matrix.php == '8.3' && matrix.deps == 'latest' && 'xdebug' || 'none' }}
tools: composer:v2

- name: Get Composer cache directory
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

- name: Cache Composer dependencies
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: composer-${{ runner.os }}-php${{ matrix.php }}-${{ matrix.deps }}-${{ hashFiles('**/composer.lock') }}
restore-keys: composer-${{ runner.os }}-php${{ matrix.php }}-

- name: Install latest dependencies
if: matrix.deps == 'latest'
run: composer install --no-interaction --prefer-dist --no-progress

- name: Install lowest dependencies
if: matrix.deps == 'lowest'
run: composer update --no-interaction --prefer-dist --no-progress --prefer-lowest

- name: Run tests (with coverage)
if: matrix.php == '8.3' && matrix.deps == 'latest'
run: vendor/bin/phpunit --coverage-clover=build/coverage/clover.xml

- name: Run tests (no coverage)
if: matrix.php != '8.3' || matrix.deps != 'latest'
run: vendor/bin/phpunit --no-coverage

- name: Upload coverage to Codecov
if: matrix.php == '8.3' && matrix.deps == 'latest'
uses: codecov/codecov-action@v4
with:
files: build/coverage/clover.xml
fail_ci_if_error: false

# ──────────────────────────────────────────────────────────────────
# Code Style — PHP CS Fixer (future gate, currently informational)
# ──────────────────────────────────────────────────────────────────
codestyle:
name: "Code Style (dry-run)"
runs-on: ubuntu-latest
continue-on-error: true # informational until .php-cs-fixer.php is added

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

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: "8.3"
coverage: none
tools: composer:v2, cs2pr

- name: Install dependencies
run: composer install --no-interaction --prefer-dist --no-progress

- name: Check if php-cs-fixer is installed
id: check-fixer
run: |
if [ -f vendor/bin/php-cs-fixer ]; then
echo "installed=true" >> $GITHUB_OUTPUT
else
echo "installed=false" >> $GITHUB_OUTPUT
fi

- name: Run PHP CS Fixer (dry-run)
if: steps.check-fixer.outputs.installed == 'true'
run: vendor/bin/php-cs-fixer fix --dry-run --diff --format=checkstyle | cs2pr

# ──────────────────────────────────────────────────────────────────
# Security Audit
# ──────────────────────────────────────────────────────────────────
security:
name: "Security Audit"
runs-on: ubuntu-latest

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

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: "8.3"
coverage: none
tools: composer:v2

- name: Install dependencies
run: composer install --no-interaction --prefer-dist --no-progress

- name: Composer audit
run: composer audit --no-interaction
57 changes: 57 additions & 0 deletions .github/workflows/feature_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Feature Request
description: Suggest a new component, API improvement, or enhancement
labels: ["enhancement", "needs-triage"]
body:
- type: markdown
attributes:
value: |
Have an idea? We'd love to hear it. Please describe your feature request below.

- type: textarea
id: problem
attributes:
label: Problem / motivation
description: What problem does this feature solve? What are you trying to do that isn't possible today?
validations:
required: true

- type: textarea
id: solution
attributes:
label: Proposed solution
description: Describe the feature you'd like to see. Include example code / API design if possible.
placeholder: |
```php
// Example of how the new API would look
$result = (new MyNewComponent('Question'))->option1()->run();
```
validations:
required: true

- type: textarea
id: alternatives
attributes:
label: Alternatives considered
description: Any alternative approaches or workarounds you've tried.
validations:
required: false

- type: dropdown
id: area
attributes:
label: Area
multiple: true
options:
- "New component"
- "Existing component improvement"
- "AbstractCommand / CLIApplication"
- "IOInterface / IO layer"
- "Shell integration"
- "Colors / Terminal"
- "Testing utilities"
- "Documentation"
- "Performance"
- "Windows support"
- "Other"
validations:
required: true
94 changes: 94 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
name: Release

on:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]*"

permissions:
contents: write

jobs:
# ──────────────────────────────────────────────────────────────────
# Gate: Tests must pass before a release is published
# ──────────────────────────────────────────────────────────────────
test-gate:
name: "Pre-release test gate"
runs-on: ubuntu-latest

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

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: "8.3"
extensions: mbstring, pcntl, posix
coverage: none
tools: composer:v2

- name: Install dependencies
run: composer install --no-interaction --prefer-dist --no-progress

- name: PHPStan
run: vendor/bin/phpstan analyse

- name: PHPUnit
run: vendor/bin/phpunit --no-coverage

# ──────────────────────────────────────────────────────────────────
# Publish GitHub Release with auto-generated changelog
# ──────────────────────────────────────────────────────────────────
release:
name: "Publish GitHub Release"
runs-on: ubuntu-latest
needs: test-gate

steps:
- name: Checkout (full history for changelog)
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Extract version from tag
id: version
run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT

- name: Generate changelog from git log
id: changelog
run: |
PREVIOUS_TAG=$(git tag --sort=-version:refname | sed -n '2p')
if [ -z "$PREVIOUS_TAG" ]; then
RANGE="HEAD"
else
RANGE="${PREVIOUS_TAG}..HEAD"
fi

echo "CHANGELOG<<EOF" >> $GITHUB_OUTPUT
git log "$RANGE" \
--pretty=format:"- %s ([%h](https://github.com/${{ github.repository }}/commit/%H))" \
--no-merges \
>> $GITHUB_OUTPUT
echo "" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
name: "php-io-cli v${{ steps.version.outputs.VERSION }}"
body: |
## What's Changed

${{ steps.changelog.outputs.CHANGELOG }}

## Installation

```bash
composer require alfacode-team/php-io-cli:^${{ steps.version.outputs.VERSION }}
```

**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.version.outputs.PREVIOUS_TAG }}...${{ github.ref_name }}
draft: false
prerelease: ${{ contains(github.ref_name, '-') }}
Loading
Loading