commit e1d41c1e9f65719d87e5ad19b14906f6e4f4e02b Author: Zhongwei Li Date: Sun Nov 30 08:43:24 2025 +0800 Initial commit diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..f035c5f --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,12 @@ +{ + "name": "typo3-core-contributions", + "description": "Guide contributions to TYPO3 core following official contribution guidelines. Includes patch creation, Gerrit workflow, coding guidelines, testing requirements, and review processes for contributing to the TYPO3 core.", + "version": "1.4.0-20251114", + "author": { + "name": "Netresearch DTT GmbH", + "email": "info@netresearch.de" + }, + "skills": [ + "./" + ] +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..813c6cd --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +# OS files +.DS_Store +Thumbs.db + +# Editor files +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# Temporary files +*.tmp +*.bak +.*.tmp + +# Log files +*.log + +# Development files +.env +.env.local diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d9802f6 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Netresearch DTT GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..f7b8881 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# typo3-core-contributions + +Guide contributions to TYPO3 core following official contribution guidelines. Includes patch creation, Gerrit workflow, coding guidelines, testing requirements, and review processes for contributing to the TYPO3 core. diff --git a/SKILL.md b/SKILL.md new file mode 100644 index 0000000..284041a --- /dev/null +++ b/SKILL.md @@ -0,0 +1,1060 @@ +--- +name: typo3-core-contributions +version: 1.4.0 +description: | + Guide contributors through the complete TYPO3 Core contribution workflow from account setup to patch submission + for both code and documentation contributions. + + Trigger when: working with TYPO3 Forge issues (forge.typo3.org/issues/*), preparing patches for TYPO3 Core, + contributing to TYPO3 (code or documentation), submitting patches to Gerrit (review.typo3.org) or GitHub PRs + (TYPO3-Documentation/*), fixing TYPO3 bugs, managing WIP state, or debugging CI failures. + + Covers: Account setup, environment configuration with DDEV, commit message formatting, Gerrit review workflow, + GitHub PR workflow for documentation, WIP state management (command-line and web UI), CI/CD debugging (CGL, + PHPStan, unit tests), troubleshooting (60+ scenarios), code quality enforcement, and systematic patch submission + for both code and documentation repositories. +license: Complete terms in LICENSE +--- + +# TYPO3 Core Contributions + +## When to Use This Skill + +Activate when the user: +- Provides a TYPO3 Forge issue URL (e.g., `https://forge.typo3.org/issues/105737`) +- Mentions contributing to TYPO3 Core, submitting patches, or fixing TYPO3 bugs +- Needs help with Gerrit review workflow, rebasing, or patch updates +- Wants to create a new Forge issue for a bug or feature +- Requests TYPO3 development environment setup +- Asks about TYPO3 commit message format or contribution guidelines + +## Scope: TYPO3 Core Contributions (Code AND Documentation) + +**This skill covers**: All TYPO3 Core contributions +- **Core Code**: PHP, JavaScript, CSS, tests via Gerrit (review.typo3.org) +- **Core Documentation**: TYPO3CMS-Guide-* repositories via GitHub Pull Requests +- Forge issue tracking (for both code and documentation) +- Commit message standards +- Contribution workflow guidance + +**Repository-Specific Workflows**: + +### Core Code (typo3/typo3) +- **Submission**: Gerrit (review.typo3.org) +- **Validation**: Git commit-msg hooks +- **CI/CD**: GitLab pipelines +- **Format**: PHP, JavaScript, CSS, YAML +- **This skill handles**: Complete workflow + +### Core Documentation (TYPO3-Documentation/*) +- **Submission**: GitHub Pull Requests +- **Validation**: GitHub Actions / pre-commit hooks +- **CI/CD**: GitHub Actions +- **Format**: reStructuredText (.rst files) +- **This skill handles**: GitHub PR workflow, commit standards + +**Integration with typo3-docs-skill**: +- **typo3-docs-skill**: Validates and writes TYPO3 documentation format (reStructuredText) + - Use for: Documentation structure, formatting, rendering + - Validates: Extension docs, Core docs, any TYPO3 documentation + - URL: https://github.com/netresearch/typo3-docs-skill +- **This skill (typo3-core-contributions)**: Handles contribution workflow + - Use for: GitHub PR process, commit messages, review coordination + +**Example from real experience (Issue #105737)**: +``` +✅ Core code fix → This skill → Gerrit submission (#91302) +✅ Documentation fix → This skill → GitHub PR (#397) +✅ Documentation validation → typo3-docs-skill → Format checking +``` + +When we fixed issue #105737: +1. Used **this skill** to submit Core code patch via Gerrit +2. Discovered docs error in commit message guide +3. Used **this skill** to create GitHub PR to TYPO3CMS-Guide-ContributionWorkflow +4. Could use **typo3-docs-skill** to validate reStructuredText formatting + +**When to use each skill**: +- **typo3-core-contributions** (this): For CONTRIBUTING to TYPO3 (code or docs) +- **typo3-docs-skill**: For WRITING/VALIDATING documentation format + +## Workflow Decision Tree + +Determine the user's current state and guide accordingly: + +``` +User starts contribution workflow +├─ Has Forge issue URL? +│ ├─ Yes → Proceed to Prerequisites Check +│ └─ No → Guide to Issue Creation Phase +├─ Prerequisites verified? +│ ├─ Yes → Proceed to Development Phase +│ └─ No → Guide through Setup Phase +├─ Patch ready? +│ ├─ Yes → Proceed to Submission Phase +│ └─ No → Guide through Development Phase +└─ Patch submitted? + ├─ Yes → Guide through Review & Update Phase + └─ No → Prepare for Gerrit submission +``` + +## Prerequisites Check + +Before beginning any contribution work, verify the user has: + +1. **Required Accounts**: + - TYPO3.org account (my.typo3.org) + - Gerrit account with SSH keys (review.typo3.org) + - Slack access (typo3.slack.com) for #typo3-cms-coredev channel + +2. **Development Environment**: + - Git configured with TYPO3 settings + - TYPO3 Core repository cloned + - DDEV-based development environment (preferred) + - Git hooks installed (commit-msg, pre-commit) - see `references/commit-msg-hook.md` for validation details + +3. **Skill Integrations**: + - `typo3-ddev-skill` for environment management + - `typo3-docs-skill` for documentation contributions (optional) + - `typo3-conformance-skill` for code quality checks (optional) + +Run `scripts/verify-prerequisites.sh` to check all prerequisites. If any are missing, proceed to the Setup Phase. + +**⚠️ Critical Email Requirement**: Your Git email MUST match one of your registered Gerrit emails or all pushes will be rejected: +- Check registered emails: https://review.typo3.org/settings#EmailAddresses +- Verify Git config: `git config user.email` +- If mismatch, update Git: `git config user.email "your-registered@email.com"` +- This verification is included in `verify-prerequisites.sh` + +## Phase 1: Account Setup + +### Check Existing Accounts + +Ask the user: +- "Do you have a TYPO3.org account?" +- "Have you set up Gerrit SSH access?" +- "Are you in the TYPO3 Slack workspace?" + +### Guide Account Creation + +If accounts are missing, load `references/account-setup.md` for detailed instructions: + +**TYPO3.org Account**: +- Visit https://my.typo3.org/index.php?id=2 +- Register with username, email, full name, and strong password +- Verify email +- This account provides access to Forge and Gerrit + +**Gerrit SSH Setup**: +- Sign in to https://review.typo3.org with TYPO3.org credentials +- Generate SSH key pair (platform-specific instructions in reference) +- Add public key to Gerrit: Profile → SSH Keys +- Test connection: `ssh -p 29418 @review.typo3.org` + +**Slack Access**: +- Join TYPO3 Slack: https://typo3.slack.com +- Required channel: #typo3-cms-coredev +- Optional channels: #typo3-cms, #random + +Verify completion before proceeding to next phase. + +## Phase 2: Environment Setup + +### Quick Setup Options + +**Option 1: Automated Setup (Recommended for Beginners)** +```bash +./scripts/setup-typo3-coredev.sh +``` +Interactive script that guides through complete setup. See below for details. + +**Option 2: Use typo3-ddev-skill** +``` +Use typo3-ddev-skill for complete DDEV setup +``` +If available, use the typo3-ddev-skill for guided setup. + +**Option 3: Manual Setup** +Follow the comprehensive workflow in `references/ddev-setup-workflow.md` for step-by-step instructions. + +### Automated Setup Script + +The `scripts/setup-typo3-coredev.sh` script provides complete automated setup: + +**What it does**: +- Checks prerequisites (Git, DDEV, Docker) +- Gathers configuration (project name, credentials, PHP version) +- Clones TYPO3 Core repository +- Configures Git for Gerrit submissions +- Sets up DDEV with optimal settings +- Installs dependencies and TYPO3 +- Activates development extensions +- Generates test data (optional) + +**Usage**: +```bash +cd /path/to/your/projects/ +./path/to/scripts/setup-typo3-coredev.sh +``` + +**Interactive prompts**: +- Project name (e.g., t3coredev-14-php8-4) +- Your name for Git commits +- Your email +- Gerrit username +- PHP version (8.2, 8.3, 8.4) +- Timezone +- TYPO3 admin password + +The script handles all configuration and creates a fully functional development environment. + +### Manual DDEV Setup (If Automation Not Suitable) + +If `typo3-ddev-skill` is not available and you prefer manual setup: + +**Clone TYPO3 Repository**: +```bash +mkdir typo3-contribution && cd typo3-contribution +git clone git@github.com:typo3/typo3.git . +``` + +**Configure Git for TYPO3**: +```bash +# User identity (required) +git config user.name "Your Name" +git config user.email "your-email@example.org" + +# Auto-rebase (required) +git config branch.autosetuprebase remote + +# Gerrit push configuration (required) +git config remote.origin.pushurl ssh://@review.typo3.org:29418/Packages/TYPO3.CMS.git +git config remote.origin.push +refs/heads/main:refs/for/main +``` + +**Install Git Hooks**: +```bash +composer gerrit:setup +``` + +Or manually copy from `Build/git-hooks/` to `.git/hooks/` and make executable. + +**Set Up Commit Template** (optional but recommended): +Copy `assets/commit-template.txt` to `~/.gitmessage.txt`: +```bash +git config commit.template ~/.gitmessage.txt +``` + +### Verify Setup + +Run verification checks: +```bash +# Check git configuration +git config -l | grep -E "user\.|remote\.origin\.|branch\.autosetuprebase" + +# Test Gerrit connection +ssh -p 29418 @review.typo3.org + +# Verify hooks exist +ls -la .git/hooks/commit-msg .git/hooks/pre-commit +``` + +All checks must pass before proceeding. + +## Phase 3: Issue Management + +### Working with Existing Forge Issue + +If user provides a Forge issue URL (e.g., `https://forge.typo3.org/issues/105737`): + +1. **Fetch and analyze the issue**: + ``` + Use WebFetch to extract: + - Issue title and description + - Issue number (e.g., #105737) + - Status and category + - Affected TYPO3 version + - Steps to reproduce + - Expected vs actual behavior + - Any existing patches or comments + ``` + +2. **Determine contribution scope**: + - Bugfix → `[BUGFIX]` commit type + - New feature → `[FEATURE]` commit type (main branch only) + - Refactoring/cleanup → `[TASK]` commit type + - Documentation → `[DOCS]` commit type + - Security → `[SECURITY]` commit type + +3. **Check for existing patches**: + - Search Gerrit: https://review.typo3.org + - Look for Change-Id or related patches + - Coordinate if others are working on it + +### Creating New Forge Issue + +If user has a bug but no issue yet: + +1. **Gather issue information**: + - What is broken or what feature is needed? + - Steps to reproduce (for bugs) + - Expected behavior vs actual behavior + - TYPO3 version affected + - Error messages or logs + +2. **Create issue on Forge**: + - Visit https://forge.typo3.org/projects/typo3cms-core/issues/new + - Fill in all required fields + - Category: Choose appropriate area (Backend, Frontend, etc.) + - Priority: Should have (most common), Must have, Could have + - Set target version if known + +3. **Note the issue number** for commit message later + +**Important**: Every patch must have a matching Forge issue before submission. + +### Creating Forge Issues Programmatically (Advanced) + +For automation or when web UI is not accessible, Forge issues can be created via the Redmine REST API: + +**Prerequisites**: +- Get API key from https://forge.typo3.org/my/account (under "API access key") +- Store securely as environment variable: `FORGE_API_KEY` + +**Using the script**: +```bash +# Set your API key +export FORGE_API_KEY="your-api-key-here" + +# Create issue +./scripts/create-forge-issue.sh +``` + +The script interactively prompts for: +- Subject line +- Description +- Tracker type (Bug, Feature, Task) +- Category (e.g., Backend, Frontend, Indexed Search) +- Priority (Should have, Must have, Could have) +- TYPO3 version affected + +**Manual API usage**: +```bash +curl -X POST \ + -H "Content-Type: application/json" \ + -H "X-Redmine-API-Key: $FORGE_API_KEY" \ + -d '{ + "issue": { + "project_id": "typo3cms-core", + "subject": "Issue title", + "description": "Detailed description", + "tracker_id": 1, + "category_id": 975, + "priority_id": 4, + "custom_fields": [ + {"id": 4, "value": "13"} + ] + } + }' \ + https://forge.typo3.org/issues.json +``` + +**Common IDs** (query full list via API): +- Trackers: 1=Bug, 2=Feature, 4=Task +- Priority: 3=Must have, 4=Should have, 5=Could have +- Categories: Use `scripts/query-forge-metadata.sh` to list all categories + +**Response includes**: +- Created issue number (for `Resolves:` line) +- Issue URL for reference + +Load `references/forge-api.md` for complete API documentation and examples. + +## Phase 4: Development + +### Create Feature Branch + +```bash +# Ensure on main branch with latest changes +git checkout main +git pull origin main + +# Create feature branch (name pattern: feature/-) +git checkout -b feature/105737-fix-indexed-search-crash +``` + +### Make Code Changes + +Guide the user through development: + +1. **Analyze the issue**: Understand root cause and scope +2. **Locate affected files**: Use code search and navigation +3. **Implement fix or feature**: + - Follow TYPO3 coding standards + - **Use framework patterns** (DI, service locators, event dispatchers) + - Check if TYPO3 already provides the pattern you need + - Add/update documentation as needed + - Consider backwards compatibility + - Add deprecations properly with `trigger_error()` (no `[!!!]` for deprecations) + - For breaking changes: Document impact on extension developers + +**Real-world insight**: Reviewers expect architectural alignment with TYPO3 framework patterns. +Don't reinvent what the framework provides. Study `Services.yaml` patterns and use dependency +injection over manual instance management. + +4. **Write tests**: + - Unit tests for isolated functionality + - Functional tests for integrated behavior + - Follow existing test patterns in codebase + - **Use typo3-testing-skill** for comprehensive test writing: + ``` + Activate typo3-testing-skill for: + - Writing unit tests for new functionality + - Creating functional tests for integrations + - Understanding TYPO3 test patterns + - Setting up test fixtures and data + - Running and debugging tests locally + ``` + +5. **Build frontend assets** (if needed): + - SCSS → CSS compilation + - JavaScript/TypeScript bundling + - Run build commands: `npm run build` or similar + +6. **Create changelog entries** (if needed): + - Breaking changes require changelog + - New features should have changelog + - Location: `Build/CHANGELOG/` + +### Code Quality Validation + +**IMPORTANT**: Always validate code quality BEFORE committing. Use `typo3-conformance-skill`: + +``` +Activate typo3-conformance-skill to: +- Check TYPO3 Coding Guidelines (CGL) compliance +- Run PHP_CodeSniffer (PHPCS) validation +- Execute PHPStan static analysis +- Validate PHP syntax and compatibility +- Fix coding standard violations automatically +- Ensure code passes CI checks locally +``` + +**When to use**: +- ✅ Before first commit +- ✅ After making code changes +- ✅ Before pushing to Gerrit +- ✅ When CI checks fail + +**Benefits**: +- Catch issues locally before submission +- Faster review process (no back-and-forth on standards) +- Learn TYPO3 coding conventions +- Avoid CI pipeline failures + +### Self-Review + +Before committing, review the changes: +- Code follows TYPO3 conventions (validated with typo3-conformance-skill) +- No debug statements or console.log +- Tests pass locally (written/validated with typo3-testing-skill) +- Documentation is updated +- Changelog created if needed +- No unintended file changes + +## Phase 5: Commit Creation + +### Commit Message Format + +TYPO3 requires strict commit message formatting. Use `scripts/create-commit-message.py` for interactive generation, or follow this format: + +**Structure**: +``` +[TYPE] Subject line (max 52 chars, imperative mood) + +Detailed description of changes explaining the how and why. +Lines wrapped at 72 characters. Use bullet points with * for +multiple items. + +Resolves: #12345 +Releases: main, 13.4, 12.4 +``` + +**Commit Types**: +- `[BUGFIX]` - Bug fixes +- `[FEATURE]` - New features (main branch only) +- `[TASK]` - Refactoring, cleanup, miscellaneous +- `[DOCS]` - Documentation changes +- `[SECURITY]` - Security fixes +- `[!!!]` - Breaking change prefix (before type: `[!!!][FEATURE]`) + +**Footer Tags**: +- `Resolves: #` **(REQUIRED)** - Every commit MUST have at least one Resolves line. The commit-msg hook will reject commits without it. Closes issue on merge for features/tasks. +- `Related: #` **(OPTIONAL)** - Links related issues without closing. CANNOT be used alone - you must have at least one Resolves line in addition to any Related lines. +- `Releases: main, 13.4, 12.4` **(REQUIRED)** - Target versions (comma-separated) +- `Change-Id: I` - Auto-generated by git hook (DO NOT modify, NEVER remove) + +**Subject Line Rules**: +- Maximum 52 characters (72 absolute limit) +- Imperative mood: "Fix bug" not "Fixed bug" or "Fixes bug" +- Start with uppercase letter +- No period at the end +- Describe what now works, not what was broken + +**Description Body**: +- Explain how and why, not what (code shows what) +- Don't repeat Forge issue content +- Don't describe reproduction steps +- Keep focused on changes made +- Wrap at 72 characters (URLs can be longer) + +Load `references/commit-message-format.md` for complete specification with examples. + +### Create the Commit + +**Initial commit**: +```bash +git add . +git commit +# Edit commit message in editor (template will load if configured) +``` + +The commit-msg hook automatically adds the `Change-Id` line - never modify or remove this! + +**Validate commit message**: +Run `scripts/validate-commit-message.py` to check format compliance. + +### Amending Commits + +For subsequent changes to the same patch: +```bash +git add . +git commit --amend +# Preserve the Change-Id line! +``` + +**Important**: Keep only ONE commit on the branch. All changes should be amended into the single commit. + +## Phase 6: Gerrit Submission + +### First-Time Submission + +**Push to Gerrit**: +```bash +git push origin HEAD:refs/for/main +``` + +Or simply `git push` if defaults are configured. + +**Expected response**: +``` +remote: SUCCESS +remote: https://review.typo3.org/c/Packages/TYPO3.CMS/+/12345 [NEW] +``` + +Copy and save the review URL! + +### Post-Submission Actions + +1. **Check Continuous Integration**: + - Gerrit automatically runs tests + - Wait for CI results (usually 5-15 minutes) + - Green checkmarks = passed, red X = failed + +2. **Monitor for feedback**: + - You'll receive email notifications + - Check Gerrit review page regularly + - Join #typo3-cms-coredev on Slack + +3. **Advertise your patch** (optional, recommended for new contributors): + - Post in #typo3-cms-coredev: "I've submitted my first patch for issue #12345, would appreciate reviews: " + +## Phase 7: Review & Update Cycle + +### Understanding Review Expectations + +**IMPORTANT**: Multiple revisions (patch sets) are NORMAL and expected in TYPO3 Core. + +**Real-world examples** (from actual merged patches): +- Extbase FileUpload tests: 24 patch sets +- Record API breaking change: 14 patch sets +- DI refactoring: 9 patch sets +- Pagetree performance fix: 7 patch sets + +**What causes multiple revisions**: +- CI failures requiring fixes +- Rebases due to main branch updates +- Code quality improvements from reviewer feedback +- Architectural refinements suggested by core team +- Edge case handling +- Scope adjustments (e.g., backport constraints) + +**Mindset**: Each revision makes your patch better. High revision counts show: +- Responsiveness to feedback +- Collaborative improvement +- Thorough vetting process +- Learning framework patterns + +Load `references/gerrit-review-patterns.md` for comprehensive real-world review insights. + +### Responding to Feedback + +When reviewers request changes: + +1. **Read feedback carefully**: Understand what needs to change +2. **Respond to every comment**: Even if just "Done" or "Fixed in PS X" +3. **Make requested changes**: Update code locally +4. **Use appropriate skill**: + - Code quality issues → typo3-conformance-skill + - Test failures → typo3-testing-skill +5. **Test thoroughly**: Validate changes work +6. **Amend the commit**: + ```bash + git add . + git commit --amend + # Keep the Change-Id unchanged! + ``` +7. **Push updated patch**: + ```bash + git push origin HEAD:refs/for/main + ``` + +This creates a new patchset on the existing review. + +**Pro tip**: Don't take high revision counts personally - they're a sign of thorough review, not failure. + +### Rebasing Your Patch + +If your patch falls behind main branch: + +**Option 1: Browser-based (easiest)**: +1. Open your patch on Gerrit +2. Click "Rebase" button +3. Select "Rebase on top of the main branch" +4. Works only if no conflicts exist + +**Option 2: Command-line**: +```bash +# Fetch latest changes +git fetch origin + +# Rebase onto main +git rebase origin/main + +# If conflicts occur, resolve them: +# 1. Fix conflicts in files +# 2. git add +# 3. git rebase --continue + +# Push rebased patch +git push origin HEAD:refs/for/main +``` + +Load `references/gerrit-workflow.md` for detailed rebase and conflict resolution procedures. + +### Review Process + +**Voting System**: +- **Code Review**: -2 (reject) to +2 (approve) +- **Verified**: -1 (fails tests) to +1 (passes tests) +- **+2 from core team member** + **+1 verified** → Ready for merge + +**Typical Timeline**: +- Simple bugfixes: 1-3 days +- Complex features: 1-2 weeks +- Patches need at least 2 reviewers (one must be core team) + +## Phase 8: Merge & Completion + +### Pre-Merge + +Once approved: +- Core merger will handle final merge +- You'll receive notification when merged +- Issue status updates automatically on Forge + +### Post-Merge + +1. **Clean up local branch**: + ```bash + git checkout main + git pull origin main + git branch -D feature/105737-fix-indexed-search-crash + ``` + +2. **Update Forge issue if needed**: + - Add any follow-up notes + - Close related issues if applicable + +3. **Celebrate**: You've contributed to TYPO3 Core! 🎉 + +## Integration with Other Skills + +This skill works best when combined with specialized TYPO3 skills. Activate them proactively during the contribution workflow. + +### typo3-ddev-skill + +**Purpose**: DDEV-based development environment setup and management + +**When to activate**: +``` +Use typo3-ddev-skill when: +- Setting up TYPO3 Core development environment from scratch +- Configuring DDEV for TYPO3 +- Managing local TYPO3 instances +- Database operations and management +- Troubleshooting DDEV/Docker issues +``` + +**Integration point**: Phase 2 (Environment Setup) + +**URL**: Check if available in your environment + +### typo3-docs-skill + +**Purpose**: TYPO3 documentation format validation and writing + +**When to activate**: +``` +Use typo3-docs-skill when: +- Writing TYPO3 documentation (Core or Extension) +- Validating reStructuredText (.rst) format and structure +- Checking documentation rendering locally +- Understanding TYPO3 documentation standards +- Fixing formatting issues in .rst files +- Creating proper cross-references and code blocks +``` + +**Integration point**: Phase 4 (Development) - for documentation contributions + +**Complementary usage**: This skill handles the contribution workflow (GitHub PRs, commit messages), +while typo3-docs-skill handles the documentation format itself. + +**URL**: https://github.com/netresearch/typo3-docs-skill + +### typo3-conformance-skill + +**Purpose**: TYPO3 Coding Guidelines (CGL) and code quality validation + +**When to activate** (PROACTIVELY): +``` +Use typo3-conformance-skill: +- BEFORE committing code changes +- After implementing new functionality +- When fixing coding standard violations +- Before pushing to Gerrit +- When CI checks fail +``` + +**Validates**: +- TYPO3 Coding Guidelines (CGL) compliance +- PHP_CodeSniffer (PHPCS) standards +- PHPStan static analysis +- PHP syntax and version compatibility +- Best practices and patterns + +**Integration points**: +- Phase 4 (Development) - Code Quality Validation section +- Phase 6 (Gerrit Submission) - Before pushing +- Phase 7 (Review & Update) - When CI fails + +**Benefits**: +- Catch issues locally before submission +- Avoid CI pipeline failures +- Faster review process +- Learn TYPO3 conventions + +**URL**: https://github.com/netresearch/typo3-conformance-skill + +### typo3-testing-skill + +**Purpose**: TYPO3 test writing and execution + +**When to activate** (PROACTIVELY): +``` +Use typo3-testing-skill when: +- Writing unit tests for new functionality +- Creating functional tests for integrations +- Writing acceptance/E2E tests +- Understanding TYPO3 test patterns and structure +- Setting up test fixtures and data providers +- Running and debugging tests locally +- Fixing failing tests +- Increasing test coverage +``` + +**Covers**: +- Unit testing (PHPUnit) +- Functional testing (database integration) +- Acceptance testing (Codeception) +- Test structure and organization +- Mocking and fixtures +- Test execution and debugging + +**Integration points**: +- Phase 4 (Development) - Writing Tests subsection +- Phase 7 (Review & Update) - When tests fail +- Before submission - Ensure tests pass + +**Benefits**: +- Write better, more maintainable tests +- Understand TYPO3 testing patterns +- Debug test failures effectively +- Ensure adequate test coverage + +**URL**: https://github.com/netresearch/typo3-testing-skill + +## Recommended Workflow with Skills + +**Complete workflow using all skills**: + +1. **Setup** → typo3-ddev-skill → Environment ready +2. **Development** → This skill → Feature branch created +3. **Code Implementation** → This skill → Code written +4. **Testing** → typo3-testing-skill → Tests written and passing +5. **Quality Check** → typo3-conformance-skill → CGL validated +6. **Documentation** (if applicable) → typo3-docs-skill → Docs formatted +7. **Commit** → This skill → Proper commit message +8. **Submit** → This skill → Gerrit/GitHub submission +9. **Review** → This skill → Handle feedback +10. **Merge** → This skill → Celebrate! 🎉 + +## Common Scenarios + +### Scenario 1: Complete First Contribution + +User: "I want to fix https://forge.typo3.org/issues/105737" + +**Workflow with skill integrations**: +1. Run prerequisites check +2. Fetch issue details from Forge +3. Verify/setup accounts if needed +4. **Use typo3-ddev-skill** → Setup/verify environment +5. Create feature branch +6. Guide through fix development +7. **Use typo3-testing-skill** → Write unit/functional tests +8. **Use typo3-conformance-skill** → Validate code quality (CGL, PHPStan) +9. Create commit with proper message +10. Submit to Gerrit +11. Monitor review process + +**Proactive skill activation**: +- Activate typo3-testing-skill when writing tests (step 7) +- Activate typo3-conformance-skill BEFORE committing (step 8) +- These skills help catch issues locally, saving review cycles + +### Scenario 2: Update Existing Patch + +User: "Reviewer asked me to change variable names in my patch" + +**Workflow with skill integrations**: +1. Verify git setup and branch +2. Guide through changes +3. **Use typo3-conformance-skill** → Validate changes meet CGL +4. Amend commit (preserve Change-Id!) +5. Push updated patchset +6. Notify reviewer on Gerrit + +**Best practice**: Always run typo3-conformance-skill after making changes to ensure +new code still passes all quality checks. + +### Scenario 3: Rebase Needed + +User: "My patch shows merge conflicts" + +**Workflow**: +1. Load `references/gerrit-workflow.md` for conflict resolution +2. Guide through rebase process +3. Help resolve conflicts if needed +4. Test after rebase +5. Push rebased patch + +### Scenario 4: Create New Issue + +User: "I found a bug in TYPO3 backend but there's no issue" + +**Workflow**: +1. Gather bug details systematically +2. Check if issue already exists on Forge +3. Guide through Forge issue creation +4. Proceed with contribution workflow + +### Scenario 5: Root Cause Analysis and Dual-Repository Fix + +User: "Documentation seems wrong, but the real issue is in the Core code" + +**Real Example from Issue #105737**: +1. **Initial symptom**: Documentation mentioned both "Resolves:" and "Fixes:" tags +2. **Investigation**: Reviewer confirmed TYPO3 uses only "Resolves:" for standardization +3. **Root cause discovery**: commit-msg hook at `Build/git-hooks/commit-msg:218` displayed misleading error message +4. **Dual-repository solution**: + - Documentation fix via GitHub PR to TYPO3CMS-Guide-ContributionWorkflow + - Core fix via Gerrit patch to update commit-msg hook error message +5. **API usage**: Created Forge issue #107881 via Redmine API +6. **Backward compatibility**: Kept validation regex accepting both, updated only user-facing message + +**Workflow**: +1. Analyze whether issue is documentation-only or has Core source +2. If Core source exists: + - Create Forge issue for Core fix + - Submit Core patch via Gerrit (this skill) + - If docs also need update, create separate PR (typo3-docs-skill) +3. Ensure both fixes reference each other +4. Balance backward compatibility with standardization + +### Scenario 6: CI Pipeline Failures + +User: "My patch was submitted but CI checks are failing" + +**Workflow with skill integrations**: +1. Check Gerrit for CI failure details +2. Identify failure type: + - **CGL/Coding Standards** → Use typo3-conformance-skill + - **PHPStan/Static Analysis** → Use typo3-conformance-skill + - **Unit/Functional Tests** → Use typo3-testing-skill + - **Build/Compilation** → This skill for troubleshooting +3. Fix issues locally using appropriate skill +4. **Validate locally BEFORE pushing**: + - Run typo3-conformance-skill for code quality + - Run typo3-testing-skill for test execution +5. Amend commit with fixes +6. Push updated patchset + +**Pro tip**: Use typo3-conformance-skill and typo3-testing-skill BEFORE first +submission to avoid CI failures entirely. Catching issues locally is faster +than waiting for CI pipelines. + +## Troubleshooting + +Common issues and solutions: + +**"Permission denied" when pushing**: +- Check SSH key configuration +- Test: `ssh -p 29418 @review.typo3.org` +- Verify pushurl: `git config remote.origin.pushurl` + +**"Missing Change-Id in commit message"**: +- Install commit-msg hook: `composer gerrit:setup` +- Or copy manually from `Build/git-hooks/commit-msg` +- Re-commit with `git commit --amend` + +**"Merge conflict" during rebase**: +- Load `references/gerrit-workflow.md` for detailed steps +- Resolve conflicts manually +- Continue: `git add . && git rebase --continue` + +**"CI tests failing"**: +- **For code quality issues** (CGL, PHPStan): Use **typo3-conformance-skill** +- **For test failures**: Use **typo3-testing-skill** +- Check specific failure details on Gerrit +- Fix issues locally with appropriate skill +- Validate locally before pushing updated patchset + +**"Coding standards violations"**: +- Use **typo3-conformance-skill** immediately +- Run PHPCS, PHPStan, and CGL checks locally +- Fix violations automatically where possible +- Learn TYPO3 conventions to avoid future violations + +Load `references/troubleshooting.md` for comprehensive troubleshooting guide. + +## Resources + +### scripts/ + +**setup-typo3-coredev.sh**: Complete automated DDEV setup (recommended for new contributors) +```bash +./scripts/setup-typo3-coredev.sh +``` +Interactive script that sets up complete TYPO3 Core development environment including Git configuration, DDEV, TYPO3 installation, and test data. + +**verify-prerequisites.sh**: Check all prerequisites (accounts, git config, environment) +```bash +./scripts/verify-prerequisites.sh +``` + +**create-commit-message.py**: Interactive commit message generator following TYPO3 format +```bash +python scripts/create-commit-message.py --issue 105737 --type BUGFIX +``` + +**validate-commit-message.py**: Validate commit message against TYPO3 requirements +```bash +python scripts/validate-commit-message.py +``` + +**create-forge-issue.sh**: Create Forge issues via Redmine REST API (interactive) +```bash +export FORGE_API_KEY="your-api-key" +./scripts/create-forge-issue.sh +``` + +**query-forge-metadata.sh**: Query Forge for available categories, trackers, and priorities +```bash +export FORGE_API_KEY="your-api-key" +./scripts/query-forge-metadata.sh +``` + +### references/ + +**ddev-setup-workflow.md**: Complete production-tested DDEV setup workflow (686 lines) +- Step-by-step manual setup instructions +- DDEV configuration details +- TYPO3 installation and extension activation +- Test data generation +- Troubleshooting and best practices + +**account-setup.md**: Detailed account creation guides (TYPO3.org, Gerrit, Slack) + +**commit-message-format.md**: Complete commit message specification with examples + +**gerrit-workflow.md**: Comprehensive Gerrit usage (review, rebase, conflicts, voting) + +**forge-api.md**: Complete Forge/Redmine REST API documentation with examples + +**commit-msg-hook.md**: Deep dive into Build/git-hooks/commit-msg validation and error messages + +**troubleshooting.md**: Common issues and solutions + +### assets/ + +**commit-template.txt**: Git commit message template for TYPO3 (copy to `~/.gitmessage.txt`) + +## Contribution Workflow Standards + +Apply these standards throughout the contribution process: + +**When managing commits**: +1. Maintain exactly one commit per patch (amend changes, never create multiple commits) +2. Preserve the auto-generated Change-Id line (never modify or remove it) +3. Validate code quality BEFORE committing using typo3-conformance-skill proactively +4. Write and execute tests locally using typo3-testing-skill before any submission +5. Always validate with typo3-conformance-skill before pushing to Gerrit + +**When maintaining patches**: +1. Rebase regularly to keep patch current with main branch +2. Self-review all changes thoroughly before pushing +3. Respond to reviewer feedback promptly (within 2-3 days maximum) +4. Leverage complementary skills (typo3-ddev-skill, typo3-docs-skill) as needed +5. Request help in #typo3-cms-coredev Slack channel when blocked + +**When writing code**: +1. Study existing code patterns in affected files before implementing +2. Follow TYPO3 framework patterns (DI, events, service configuration) +3. Use typo3-conformance-skill validation BEFORE every commit +4. Use typo3-testing-skill when writing ANY test (unit, functional, acceptance) +5. Use typo3-docs-skill for ALL documentation contributions + +**When handling CI failures**: +1. Catch issues locally first to avoid CI failures entirely +2. Fix issues locally using appropriate skill before pushing updates +3. Never skip validation to make builds pass +4. Understand root cause before applying fixes + +## References + +- **Contribution Guide**: https://docs.typo3.org/m/typo3/guide-contributionworkflow/main/en-us/ +- **Forge**: https://forge.typo3.org +- **Gerrit**: https://review.typo3.org +- **Forger** (search tool): https://forger.typo3.com +- **Slack**: https://typo3.slack.com (#typo3-cms-coredev) diff --git a/assets/commit-template.txt b/assets/commit-template.txt new file mode 100644 index 0000000..336036f --- /dev/null +++ b/assets/commit-template.txt @@ -0,0 +1,78 @@ +[BUGFIX|TASK|FEATURE|DOCS|SECURITY] Subject line (max 52 chars, imperative) + +# Detailed description explaining how and why (not what): +# - Lines wrapped at 72 characters +# - Explain context and reasoning +# - Don't repeat Forge issue content +# - Don't describe reproduction steps +# +# Use bullet points for lists: +# * First item +# * Second item +# * Third item + +Resolves: # +Releases: main, 13.4, 12.4 +# Change-Id will be added automatically by git hook - DO NOT edit manually! + +# ============================================================================ +# TYPO3 Commit Message Format Guide +# ============================================================================ +# +# SUBJECT LINE +# ------------ +# Format: [TYPE] Description +# +# Types: +# [BUGFIX] - Bug fixes +# [FEATURE] - New features (main branch only) +# [TASK] - Refactoring, cleanup, miscellaneous +# [DOCS] - Documentation changes +# [SECURITY] - Security vulnerability fixes +# +# Breaking changes: [!!!][TYPE] Description +# +# Rules: +# - Imperative mood (Fix, Add, Remove - not Fixed, Added, Removed) +# - Start with uppercase letter +# - Max 52 characters (recommended), 72 absolute limit +# - No period at end +# - Describe what now works, not what was broken +# +# DESCRIPTION BODY +# ---------------- +# - Explain HOW and WHY, not WHAT (code shows what) +# - Leave blank line after subject +# - Wrap at 72 characters (URLs can be longer) +# - Use asterisks (*) for bullet points +# +# FOOTER TAGS +# ----------- +# Resolves: #12345 - Closes issue on merge (features/tasks) +# Related: #12345 - Links issue without closing (bugfixes) +# Releases: main, 13.4 - Target versions (comma-separated) +# Change-Id: I... - Auto-generated, DO NOT modify! +# +# EXAMPLES +# -------- +# Good: +# [BUGFIX] Fix null pointer in indexed search +# [FEATURE] Add WebP image format support +# [TASK] Refactor cache manager for better performance +# [!!!][TASK] Drop support for PHP 7.4 +# +# Bad: +# [BUGFIX] fixed bug (past tense) +# [FEATURE] Adds webp support (wrong tense) +# [TASK] refactoring cache (lowercase) +# [BUGFIX] Fix null pointer exception. (period at end) +# +# VALIDATION +# ---------- +# Run: ./scripts/validate-commit-message.py +# +# MORE INFO +# --------- +# See: references/commit-message-format.md +# Docs: https://docs.typo3.org/m/typo3/guide-contributionworkflow/ +# ============================================================================ diff --git a/claudedocs/refactoring-summary.md b/claudedocs/refactoring-summary.md new file mode 100644 index 0000000..7a90039 --- /dev/null +++ b/claudedocs/refactoring-summary.md @@ -0,0 +1,52 @@ +# SKILL.md Refactoring Summary + +**Date:** 2025-11-14 +**Version Change:** 1.3.0 → 1.4.0 +**Skill:** typo3-core-contributions + +## Changes Applied + +### Pattern 1: Removed "## Overview" Section +- **Before:** Lines 21-23 contained brief "## Overview" section +- **After:** Removed entire section +- **Rationale:** Content duplicated by YAML description and "When to Use This Skill" section + +### Pattern 2: Converted "## Best Practices" to Imperative Form +- **Before:** "## Best Practices" with numbered list and subsection +- **After:** "## Contribution Workflow Standards" with imperative "When X" format +- **Changes:** + +#### When managing commits (5 standards) +- Converted from general practices to specific commit management procedures +- Emphasized proactive skill usage (typo3-conformance-skill, typo3-testing-skill) + +#### When maintaining patches (5 standards) +- Extracted patch maintenance guidance into dedicated section +- Action-oriented instructions for rebase, review, feedback + +#### When writing code (5 standards) +- Focused on code quality and framework patterns +- Clear integration points with complementary skills + +#### When handling CI failures (4 standards) +- Separated CI troubleshooting into distinct workflow +- Emphasized local validation and root cause analysis + +## Impact Analysis + +**Readability:** Improved - organized by workflow context +**Consistency:** Aligned with skill-creator best practices +**Usability:** Enhanced - clear triggers for when to apply each standard +**Workflow Integration:** Better integration with complementary skills + +## Files Modified + +- `/SKILL.md` (lines 1-1057) + +## Verification + +- Version number updated in YAML frontmatter: ✓ +- Overview section removed: ✓ +- Best Practices converted to Contribution Workflow Standards: ✓ +- All 19 standards preserved with improved organization: ✓ +- Skill integration guidance maintained: ✓ diff --git a/plugin.lock.json b/plugin.lock.json new file mode 100644 index 0000000..c6058af --- /dev/null +++ b/plugin.lock.json @@ -0,0 +1,117 @@ +{ + "$schema": "internal://schemas/plugin.lock.v1.json", + "pluginId": "gh:netresearch/claude-code-marketplace:skills/typo3-core-contributions", + "normalized": { + "repo": null, + "ref": "refs/tags/v20251128.0", + "commit": "c61099775905f80543deaa2bb5c0acde730c30b8", + "treeHash": "ed54abc6f6eb9cd127e0fbd345acb0b190438126ead558e86866cb8dd4517f7a", + "generatedAt": "2025-11-28T10:27:19.600332Z", + "toolVersion": "publish_plugins.py@0.2.0" + }, + "origin": { + "remote": "git@github.com:zhongweili/42plugin-data.git", + "branch": "master", + "commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390", + "repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data" + }, + "manifest": { + "name": "typo3-core-contributions", + "description": "Guide contributions to TYPO3 core following official contribution guidelines. Includes patch creation, Gerrit workflow, coding guidelines, testing requirements, and review processes for contributing to the TYPO3 core.", + "version": "1.4.0-20251114" + }, + "content": { + "files": [ + { + "path": "LICENSE", + "sha256": "ab373f9ef890455f235a4ccfab7ae7f1157d5edd45e659abae687b3b6255a8d6" + }, + { + "path": "README.md", + "sha256": "dbe7246fc0326d7bd94e3d1331333d36644298a5b7efbb0a88cd145c691917fd" + }, + { + "path": ".gitignore", + "sha256": "3f62ab1e721fdb95478da9f8f9da4cecdc319027d5bd50875be155096894577b" + }, + { + "path": "SKILL.md", + "sha256": "be04cc864305cd81f7c453e438b7561b9d6f55b2d6a08f97dc16de977c01525c" + }, + { + "path": "references/commit-message-format.md", + "sha256": "9b2f6e02622990792e3fb3dd9b3517bdf589fdf617177db3e62e8cdb8435ade4" + }, + { + "path": "references/ddev-setup-workflow.md", + "sha256": "d4d7ce7295626390c0a7e5d0de001905d8f1eba58c412f6f2fcf2d9756b549b8" + }, + { + "path": "references/troubleshooting.md", + "sha256": "5f2fa7356654dc27b7f49c6472ab5548b86927aad8c2452889cc04897fb69ef9" + }, + { + "path": "references/forge-api.md", + "sha256": "e7a0fc7dbe169392e851441f9f780de4015040db4bc004a418357ae157359d26" + }, + { + "path": "references/gerrit-workflow.md", + "sha256": "4495e847cf2c2865216b54670446060d721d879609a824e6a6b2ce8ec4b93c81" + }, + { + "path": "references/commit-msg-hook.md", + "sha256": "1db8b73f5ffcb3c09a23035c7b772b3db5471c07cdd4a9e3a65c2f6420581896" + }, + { + "path": "references/account-setup.md", + "sha256": "9dc89d22b729d21cf09efb6aa848237c641faa84a2c9ab234cb5297d07231756" + }, + { + "path": "references/gerrit-review-patterns.md", + "sha256": "585195c4184806acdf01e3437dcc9b97de0c7104c86886242067bbf08836de14" + }, + { + "path": "claudedocs/refactoring-summary.md", + "sha256": "0feaaf54fc2738956bf5c34829a7093a562ddb7d9f1ab468f0198a40992a347c" + }, + { + "path": "scripts/setup-typo3-coredev.sh", + "sha256": "d47c65f4cd00aab4a1c0b46323a8e96ba1c2e1d14992f94d6dce798f8113c7b0" + }, + { + "path": "scripts/create-commit-message.py", + "sha256": "c0ea29d591cbeefe21ec7a8375829bd870b6c271ff50d3f7e12717004974c28a" + }, + { + "path": "scripts/query-forge-metadata.sh", + "sha256": "aa747ec03f3fc0a8842bd1bff236ae7253ded95f24f70e6c10e7567328a40aec" + }, + { + "path": "scripts/verify-prerequisites.sh", + "sha256": "533f0555ec0f2a23088c5d11dce6193175439a68405faf2b6f5eef4251766f19" + }, + { + "path": "scripts/create-forge-issue.sh", + "sha256": "60da8c26d4fde62279923281e402ada6a81a61865e9f55b4081188b74d3a97fc" + }, + { + "path": "scripts/validate-commit-message.py", + "sha256": "3b75909562f243565927169dccaaf6c9fd5241e6bfd4b571a81aa5bca3b42db9" + }, + { + "path": ".claude-plugin/plugin.json", + "sha256": "38ac5fca0f81f268f2714c1b3cc732f8e5512c46b203070ebeea1d9fc82fcc11" + }, + { + "path": "assets/commit-template.txt", + "sha256": "9ff82d4769378bd677c2cccf167452040474c219991680a0b674b103fea9d681" + } + ], + "dirSha256": "ed54abc6f6eb9cd127e0fbd345acb0b190438126ead558e86866cb8dd4517f7a" + }, + "security": { + "scannedAt": null, + "scannerVersion": null, + "flags": [] + } +} \ No newline at end of file diff --git a/references/account-setup.md b/references/account-setup.md new file mode 100644 index 0000000..943b7d4 --- /dev/null +++ b/references/account-setup.md @@ -0,0 +1,275 @@ +# TYPO3 Core Contribution Account Setup Guide + +Complete guide for setting up all required accounts for TYPO3 Core contributions. + +## Overview + +Three accounts are required for TYPO3 Core contribution: +1. **TYPO3.org Account** - Central authentication for all TYPO3 services +2. **Gerrit Account with SSH** - Code review and patch submission +3. **Slack Access** - Community communication and support + +## 1. TYPO3.org Account + +### Registration + +1. Visit the signup page: https://my.typo3.org/index.php?id=2 + +2. Fill in the registration form: + - **Username**: Choose alphanumeric identifier (avoid special characters like `@` or `!`) + - **Email Address**: Use email for Forge and Gerrit notifications + - **Full Name**: Use real name (community values genuine identification) + - **Password**: Create strong password (use password manager recommended) + +3. Submit the form + +4. Check your email for verification message + +5. Click verification link to activate account + +### What This Account Provides + +- Access to Forge issue tracker +- Authentication for Gerrit code review +- Access to my.typo3.org profile management +- Community member identification + +### Important Notes + +- Username cannot be changed after registration +- Consider using personal email (not corporate) if contributing independently +- This account will be visible in git commits and Gerrit reviews + +## 2. Gerrit Account Setup + +### Prerequisites + +- Active TYPO3.org account +- SSH key pair (will create if needed) + +### Step 1: Sign In to Gerrit + +1. Visit https://review.typo3.org +2. Click **Sign In** button (top right) +3. Authenticate with your TYPO3.org credentials +4. You'll be redirected back to Gerrit + +### Step 2: Generate SSH Key Pair + +SSH keys are required for pushing patches to Gerrit. + +#### Linux / macOS + +```bash +# Generate SSH key pair +ssh-keygen -t ed25519 -C "your-email@example.org" + +# Default location: ~/.ssh/id_ed25519 +# Press Enter to accept default location +# Optionally set a passphrase for additional security + +# View your public key +cat ~/.ssh/id_ed25519.pub +``` + +#### Windows + +**Option A: Git Bash (Recommended)** +```bash +# Same commands as Linux/macOS above +ssh-keygen -t ed25519 -C "your-email@example.org" +``` + +**Option B: PuTTYgen** +1. Download and install PuTTY: https://www.putty.org/ +2. Run PuTTYgen +3. Click "Generate" and move mouse randomly +4. Save private key (*.ppk file) +5. Copy public key from text area + +### Step 3: Add Public Key to Gerrit + +1. Click your profile icon (top right in Gerrit) +2. Select **Settings** from dropdown +3. Click **SSH Keys** in left sidebar +4. Paste your **public key** content (entire content of `id_ed25519.pub` or `id_rsa.pub`) +5. Click **Add New SSH Key** + +**Important**: Only add the PUBLIC key, never the private key! + +### Step 4: Test SSH Connection + +```bash +# Test connection to Gerrit +ssh -p 29418 @review.typo3.org + +# Expected output: +# **** Welcome to Gerrit Code Review **** +# Hi , you have successfully connected over SSH. +``` + +If you see the welcome message, SSH is configured correctly! + +### Multiple Devices + +If you work on multiple computers: + +**Option 1: Copy Private Key** +- Copy `~/.ssh/id_ed25519` (private key) to other machines +- Set proper permissions: `chmod 600 ~/.ssh/id_ed25519` +- Not recommended for security reasons + +**Option 2: Generate Separate Keys (Recommended)** +- Generate new key pair on each device +- Add all public keys to Gerrit settings +- Gerrit supports multiple SSH keys per account +- More secure: compromised device doesn't affect others + +### Troubleshooting + +**"Permission denied (publickey)"** +- Verify key is added to Gerrit: Settings → SSH Keys +- Check key permissions: `chmod 600 ~/.ssh/id_ed25519` +- Test with verbose: `ssh -vvv -p 29418 @review.typo3.org` + +**"Connection refused"** +- Check firewall settings +- Verify port 29418 is accessible +- Try from different network + +**"Host key verification failed"** +- Accept host key: `ssh-keyscan -p 29418 review.typo3.org >> ~/.ssh/known_hosts` + +## 3. TYPO3 Slack Workspace + +### Joining Slack + +1. Visit https://typo3.slack.com + +2. Click **Create an account** or **Sign in** + +3. Use same email as TYPO3.org account (recommended for consistency) + +4. Complete Slack registration + +5. You'll receive invitation to TYPO3 workspace + +### Required Channels + +**#typo3-cms-coredev** (Essential) +- Core development discussions +- Patch review requests +- Technical questions +- Get help from core team + +### Recommended Channels + +**#typo3-cms** +- General TYPO3 CMS discussions +- User questions +- Extension development + +**#random** +- Off-topic chat +- Community social + +**#announce** +- Official announcements +- Release notifications + +### Using Slack Effectively + +**Asking for Reviews**: +``` +I've submitted a patch for issue #105737 (indexed search crash). +Would appreciate reviews: https://review.typo3.org/c/Packages/TYPO3.CMS/+/12345 +``` + +**Asking Questions**: +``` +Working on #105737, need clarification on preg_replace error handling. +Should I use fallback or throw exception? Context: [brief explanation] +``` + +**Best Practices**: +- Search before asking (knowledge base exists) +- Provide context and Forge/Gerrit links +- Be patient (volunteers respond when available) +- Use threads for discussions +- Thank people who help! + +### Slack Etiquette + +- **Don't** @here or @channel unless critical +- **Do** use threads to keep discussions organized +- **Don't** DM core team members without asking first +- **Do** share knowledge when you can help others +- **Don't** expect immediate responses (volunteers have lives!) + +## Verification Checklist + +Before proceeding with development, verify: + +- [ ] TYPO3.org account created and email verified +- [ ] Can sign in to https://forge.typo3.org +- [ ] Can sign in to https://review.typo3.org +- [ ] SSH key added to Gerrit +- [ ] SSH connection to Gerrit successful: `ssh -p 29418 @review.typo3.org` +- [ ] Joined TYPO3 Slack workspace +- [ ] Member of #typo3-cms-coredev channel + +Run `scripts/verify-prerequisites.sh` to automatically check most of these! + +## Security Best Practices + +### SSH Key Security + +- **Never share private keys** - TYPO3 team will never ask for them +- **Use strong passphrase** - Protects key if device is compromised +- **Rotate keys periodically** - Generate new keys annually +- **Delete old keys** - Remove unused keys from Gerrit settings + +### Account Security + +- **Use unique strong password** - Use password manager +- **Enable 2FA if available** - Additional security layer +- **Log out on shared devices** - Don't stay signed in +- **Review SSH keys regularly** - Remove keys from old devices + +### Privacy Considerations + +- Your name and email will be visible in: + - Git commit history + - Gerrit reviews + - Forge issue comments +- Consider using professional email if contributing as individual +- Company contributions may require corporate email + +## Next Steps + +After completing account setup: + +1. Proceed to **Environment Setup** (Phase 2 in main workflow) +2. Configure Git for TYPO3 contributions +3. Clone TYPO3 repository +4. Install Git hooks +5. Start contributing! + +## Support Resources + +- **Forge Account Issues**: https://forge.typo3.org/projects/typo3cms-core +- **Gerrit SSH Help**: https://review.typo3.org/Documentation/user-upload.html +- **Slack Support**: Ask in #typo3-cms-coredev +- **Documentation**: https://docs.typo3.org/m/typo3/guide-contributionworkflow/ + +## Quick Reference + +| Service | URL | Purpose | +|---------|-----|---------| +| TYPO3.org Registration | https://my.typo3.org/index.php?id=2 | Create account | +| TYPO3.org Profile | https://my.typo3.org | Manage profile | +| Forge | https://forge.typo3.org | Issue tracking | +| Gerrit | https://review.typo3.org | Code review | +| Gerrit SSH Test | `ssh -p 29418 @review.typo3.org` | Verify connection | +| Slack | https://typo3.slack.com | Community chat | +| Documentation | https://docs.typo3.org/m/typo3/guide-contributionworkflow/ | Full guide | diff --git a/references/commit-message-format.md b/references/commit-message-format.md new file mode 100644 index 0000000..a9b2b74 --- /dev/null +++ b/references/commit-message-format.md @@ -0,0 +1,477 @@ +# TYPO3 Commit Message Format Specification + +Complete specification for TYPO3 Core contribution commit messages with examples and validation rules. + +## Structure Overview + +``` +[TYPE] Subject line (max 52 chars recommended, 72 absolute limit) + +Detailed description explaining how and why the changes were made. +Lines wrapped at 72 characters. Explain the context and reasoning +behind the implementation approach. + +Multiple paragraphs are allowed. Use bullet points with asterisks (*) +for lists: + +* First item with detailed explanation +* Second item +* Third item + +Resolves: #12345 +Related: #12346 +Releases: main, 13.4, 12.4 +Change-Id: I1234567890abcdef1234567890abcdef12345678 +``` + +## Subject Line + +### Format + +`[TYPE] Description starting with uppercase verb in imperative mood` + +### Commit Types + +| Type | Purpose | Branch Restrictions | +|------|---------|-------------------| +| `[BUGFIX]` | Bug fixes | All branches | +| `[FEATURE]` | New functionality | main branch only | +| `[TASK]` | Refactoring, cleanup, misc | All branches | +| `[DOCS]` | Documentation changes | All branches | +| `[SECURITY]` | Security vulnerability fixes | All branches | + +### Breaking Changes + +Use `[!!!]` prefix before type for breaking changes: + +``` +[!!!][FEATURE] Remove deprecated TypoScript syntax + +[!!!][TASK] Drop support for PHP 7.4 +``` + +**Important**: Deprecations must NOT use `[!!!]` prefix! + +### Length Limits + +- **Recommended**: 52 characters +- **Absolute maximum**: 72 characters +- Breaking changes get 5 extra chars: `[!!!]` is not counted against limit + +### Imperative Mood + +Subject must use imperative present tense (command form): + +✅ **Correct**: +- `Fix memory leak in cache manager` +- `Add support for WebP images` +- `Remove deprecated method calls` +- `Update documentation for hooks` + +❌ **Wrong**: +- `Fixed memory leak` (past tense) +- `Fixing memory leak` (present continuous) +- `Fixes memory leak` (present tense) +- `Memory leak fix` (noun phrase) + +**Test**: "If applied, this commit will _[your subject]_" +- "If applied, this commit will **fix memory leak**" ✅ +- "If applied, this commit will **fixed memory leak**" ❌ + +### Capitalization + +- Start description with uppercase letter after `[TYPE]` +- No period at the end + +✅ `[BUGFIX] Fix null pointer exception in indexer` +❌ `[BUGFIX] fix null pointer exception in indexer` +❌ `[BUGFIX] Fix null pointer exception in indexer.` + +### What to Describe + +Describe **what now works**, not what was broken: + +✅ `Allow cancelling file exists modal` +❌ `Cancelling the file exists modal works now` + +✅ `Limit element browser to default language pages` +❌ `Element Browser should only render default language pages` + +## Description Body + +### Purpose + +Explain the **how** and **why** of changes, not the **what** (code shows what). + +### Guidelines + +- Wrap lines at 72 characters (URLs can be longer) +- Leave blank line after subject +- Explain context and reasoning +- **Don't** repeat Forge issue content +- **Don't** describe reproduction steps (belong in Forge) +- **Do** explain non-obvious implementation choices +- **Do** mention side effects or impacts + +### Bullet Points + +Use asterisks (`*`) with hanging indents: + +``` +This change improves performance by: + +* Caching compiled templates in memory +* Reducing database queries from N+1 to 1 +* Pre-loading frequently accessed resources +``` + +### Long URLs + +Lines exceeding 72 chars are acceptable for URLs. Use numbered references: + +``` +This implements the W3C recommendation [1] for accessible forms. + +Additional context can be found in the TYPO3 RFC [2]. + +[1] https://www.w3.org/WAI/WCAG21/Understanding/labels-or-instructions.html +[2] https://wiki.typo3.org/Category:T3DD12/Sessions/Accessibility +``` + +## Footer Tags + +### Required Format + +`Tag: value` (colon followed by space) + +### Resolves **(REQUIRED)** + +Closes Forge issue when patch is merged: + +``` +Resolves: #12345 +``` + +Multiple issues (one per line): +``` +Resolves: #12345 +Resolves: #12346 +``` + +**Critical Rule**: Every commit MUST have at least one `Resolves:` line. The commit-msg hook will reject commits without it. + +**When to use**: +- Features: MUST use Resolves +- Tasks: MUST use Resolves +- Bugfixes: MUST use Resolves +- All commit types: ALWAYS use Resolves + +**Note**: For features and tasks, `Resolves:` closes the issue on merge. For bugfixes, you can use `Related:` in addition to `Resolves:` if needed, but `Resolves:` is still mandatory. + +### Related **(OPTIONAL)** + +Links issue without closing it: + +``` +Related: #12345 +``` + +**Critical Rule**: `Related:` CANNOT be used alone - you MUST have at least one `Resolves:` line in addition to any `Related:` lines. The commit-msg hook will reject commits with only `Related:` tags. + +**When to use** (in addition to Resolves): +- Bugfixes: Use Related for issues that should stay open +- Partial fixes: Related for multi-step fixes where issue remains open +- Context: Link related discussions or issues +- Cross-references: Link to related work or documentation + +### Releases + +Target versions (comma-separated): + +``` +Releases: main, 13.4, 12.4 +``` + +**Format**: +- `main` - Current development branch +- `13.4` - Patch release version +- `12.4` - LTS version + +**Rules**: +- Always include target versions +- List from newest to oldest +- Features go to `main` only +- Bugfixes can target multiple releases + +### Change-Id + +Auto-generated by git commit-msg hook: + +``` +Change-Id: I1234567890abcdef1234567890abcdef12345678 +``` + +**Critical Rules**: +- **NEVER** manually add Change-Id +- **NEVER** modify existing Change-Id +- **NEVER** remove Change-Id +- Git hook generates this automatically +- Required for Gerrit to track patch updates + +### Depends (Documentation Only) + +For documentation patches referencing core changes: + +``` +Depends: I1234567890abcdef1234567890abcdef12345678 +``` + +Only used in typo3/cms-docs repository. + +### Reverts + +For reverting patches: + +``` +[TASK] Revert "[FEATURE] Introduce YAML imports" + +This reverts commit abc123def456. + +Resolves: #12347 +Reverts: I1234567890abcdef1234567890abcdef12345678 +``` + +## Complete Examples + +### Example 1: Bugfix + +``` +[BUGFIX] Prevent null pointer in indexed search + +The preg_replace function returns null on PCRE errors like +PREG_BAD_UTF8_ERROR. Passing null to mb_strcut triggers TypeError +in PHP 8.2+. + +Add null check with fallback to original content, ensuring type +safety while maintaining graceful degradation for malformed input. + +Resolves: #105737 +Releases: main, 13.4, 12.4 +Change-Id: I1234567890abcdef1234567890abcdef12345678 +``` + +### Example 2: Feature + +``` +[FEATURE] Add WebP image format support + +Implement WebP processing in image manipulation stack: + +* Add WebP MIME type detection +* Integrate libwebp encoding/decoding +* Update image quality settings for WebP +* Add configuration options for compression + +WebP provides 25-30% better compression than JPEG while maintaining +quality, significantly improving page load times. + +Resolves: #98765 +Releases: main +Change-Id: Iabcdef1234567890abcdef1234567890abcdef12 +``` + +### Example 3: Task with Breaking Change + +``` +[!!!][TASK] Drop PHP 7.4 support + +PHP 7.4 reached end-of-life in November 2022 and no longer receives +security updates. Remove compatibility code and leverage PHP 8.0+ +features: + +* Remove PHP 7.4 compatibility polyfills +* Update composer.json to require PHP >= 8.0 +* Use union types and match expressions +* Enable strict type declarations globally + +Resolves: #99888 +Releases: main +Change-Id: I9876543210fedcba9876543210fedcba98765432 +``` + +### Example 4: Documentation + +``` +[DOCS] Update contribution workflow guide + +Clarify git setup instructions and add troubleshooting section +for common SSH key issues reported in #typo3-cms-coredev. + +Related: #12345 +Releases: main +Change-Id: Iaa11bb22cc33dd44ee55ff66gg77hh88ii99jj00 +``` + +## Validation Rules + +### Subject Line + +- [ ] Starts with valid commit type: `[BUGFIX]`, `[FEATURE]`, `[TASK]`, `[DOCS]`, or `[SECURITY]` +- [ ] Breaking changes use `[!!!]` prefix correctly +- [ ] Description starts with uppercase letter +- [ ] Uses imperative mood +- [ ] No period at end +- [ ] Length ≤ 52 chars (recommended) or ≤ 72 chars (absolute) +- [ ] No extension names (EXT:) in subject + +### Body + +- [ ] Blank line after subject (if body exists) +- [ ] Lines wrapped at 72 chars (except URLs) +- [ ] Explains how and why, not what +- [ ] No reproduction steps (belong in Forge) + +### Footer + +- [ ] `Resolves:` present **(REQUIRED for ALL commits)** + **Critical**: The commit-msg hook WILL REJECT commits without at least one `Resolves:` line +- [ ] `Related:` used only in addition to `Resolves:` (optional, cannot be used alone) +- [ ] `Releases:` present with valid versions +- [ ] `Change-Id:` present (added by hook) +- [ ] Proper format: `Tag: value` (colon + space) +- [ ] Issue references use `#` prefix: `#12345` + +## Common Mistakes + +### ❌ Wrong: Vague Subject + +``` +[TASK] Improve extension configuration +``` + +### ✅ Correct: Specific Subject + +``` +[TASK] Add validation for extension configuration arrays +``` + +--- + +### ❌ Wrong: Past Tense + +``` +[BUGFIX] Fixed cache invalidation in frontend +``` + +### ✅ Correct: Imperative Mood + +``` +[BUGFIX] Fix cache invalidation in frontend +``` + +--- + +### ❌ Wrong: No Footer Tags + +``` +[FEATURE] Add dark mode support + +Implements dark mode toggle with user preference storage. +``` + +### ✅ Correct: Complete Footer + +``` +[FEATURE] Add dark mode support + +Implements dark mode toggle with user preference storage. + +Resolves: #12345 +Releases: main +Change-Id: I1234567890abcdef1234567890abcdef12345678 +``` + +--- + +### ❌ Wrong: Comma-Separated Issues + +``` +Resolves: #12345, #12346, #12347 +``` + +### ✅ Correct: One Per Line + +``` +Resolves: #12345 +Resolves: #12346 +Resolves: #12347 +``` + +--- + +### ❌ Wrong: Missing Space After Colon + +``` +Releases:main, 13.4 +``` + +### ✅ Correct: Space After Colon + +``` +Releases: main, 13.4 +``` + +## Tools + +### Validation + +Use `scripts/validate-commit-message.py`: + +```bash +# Validate last commit +./scripts/validate-commit-message.py + +# Validate specific file +./scripts/validate-commit-message.py --file commit-msg.txt + +# Strict mode (warnings as errors) +./scripts/validate-commit-message.py --strict +``` + +### Generation + +Use `scripts/create-commit-message.py`: + +```bash +# Interactive generator +./scripts/create-commit-message.py --issue 105737 --type BUGFIX + +# With breaking change +./scripts/create-commit-message.py --issue 98765 --type FEATURE --breaking +``` + +### Template + +Copy `assets/commit-template.txt` to `~/.gitmessage.txt`: + +```bash +git config --global commit.template ~/.gitmessage.txt +``` + +## References + +- **Official Guide**: https://docs.typo3.org/m/typo3/guide-contributionworkflow/main/en-us/Appendix/CommitMessage.html +- **Gerrit Documentation**: https://review.typo3.org/Documentation/ +- **TYPO3 Forge**: https://forge.typo3.org + +## Quick Reference + +| Element | Format | Example | +|---------|--------|---------| +| Bugfix | `[BUGFIX] Description` | `[BUGFIX] Fix null pointer in indexer` | +| Feature | `[FEATURE] Description` | `[FEATURE] Add WebP support` | +| Task | `[TASK] Description` | `[TASK] Refactor cache manager` | +| Breaking | `[!!!][TYPE] Description` | `[!!!][TASK] Drop PHP 7.4 support` | +| Resolves | `Resolves: #12345` | Closes issue on merge | +| Related | `Related: #12345` | Links without closing | +| Releases | `Releases: main, 13.4` | Target versions | diff --git a/references/commit-msg-hook.md b/references/commit-msg-hook.md new file mode 100644 index 0000000..4345b81 --- /dev/null +++ b/references/commit-msg-hook.md @@ -0,0 +1,460 @@ +# TYPO3 Commit Message Hook + +Deep dive into the `Build/git-hooks/commit-msg` hook: validation rules, error messages, and troubleshooting. + +## Overview + +The commit-msg hook is a Git client-side hook that validates commit messages before they're created. TYPO3 uses this to enforce commit message standards and automatically add Change-Id for Gerrit tracking. + +**Location**: `Build/git-hooks/commit-msg` +**Installed to**: `.git/hooks/commit-msg` + +## Installation + +### Automated (Recommended) + +```bash +composer gerrit:setup +``` + +This command: +1. Copies hook from `Build/git-hooks/commit-msg` to `.git/hooks/commit-msg` +2. Makes it executable +3. Sets up Gerrit configuration + +### Manual + +```bash +# Copy hook +cp Build/git-hooks/commit-msg .git/hooks/commit-msg + +# Make executable +chmod +x .git/hooks/commit-msg +``` + +### Verify Installation + +```bash +# Check if hook exists and is executable +ls -la .git/hooks/commit-msg + +# Expected output: +# -rwxr-xr-x 1 user group 8192 Dec 15 10:00 .git/hooks/commit-msg +``` + +## Hook Functions + +### 1. Change-Id Generation + +**Purpose**: Auto-generate unique Change-Id for Gerrit patch tracking + +**Function**: `add_ChangeId()` + +**Behavior**: +- Generates unique hash based on commit content +- Adds `Change-Id: I` to commit message footer +- Skips if Change-Id already exists +- Skips for fixup!/squash! commits +- Places Change-Id after Resolves/Releases footer + +**Format**: +``` +Change-Id: I1234567890abcdef1234567890abcdef12345678 +``` + +**Critical Rules**: +- NEVER manually add Change-Id +- NEVER modify existing Change-Id +- NEVER remove Change-Id +- Same Change-Id = same patch (for updates) +- Different Change-Id = new patch + +### 2. Line Length Validation + +**Function**: `checkForLineLength()` + +**Rules**: +- Maximum line length: 72 characters +- Applies to subject and body +- Excludes comment lines (starting with `#`) +- URLs can exceed limit + +**Error Message**: +``` +The maximum line length of 72 characters is exceeded. +``` + +**Location**: Line 200 in hook + +### 3. Commit Type Validation + +**Function**: `checkForCommitType()` + +**Rules**: +- First line must contain commit type in brackets +- Valid types: `[BUGFIX]`, `[FEATURE]`, `[TASK]`, `[DOCS]`, `[SECURITY]` +- Breaking changes: `[!!!][TYPE]` + +**Regex**: `/^\[^]]+\] .+$/` + +**Error Message**: +``` +Your first line has to contain a commit type like '[BUGFIX]'. +``` + +**Location**: Line 209 in hook + +### 4. Resolves Tag Validation + +**Function**: `checkForResolves()` + +**Rules**: +- Every commit MUST have at least one `Resolves:` or `Fixes:` line +- Format: `Resolves: #` or `Fixes: #` +- Must be on separate line (not inline) +- Issue number must be numeric + +**Regex**: `/^(Resolves|Fixes): #[0-9]+$/` + +**Error Message** (as of v1.1): +``` +You need at least one 'Resolves|Fixes: #' line. +``` + +**Updated Message** (as of v1.2, see Issue #107881): +``` +You need at least one 'Resolves: #' line. +``` + +**Location**: Line 218 in hook + +**Important Context**: +- The regex accepts both `Resolves:` and `Fixes:` for backward compatibility +- TYPO3 community standard is to use ONLY `Resolves:` +- The error message guides users toward the standard +- This was the source of documentation confusion in Issue #105737 + +### 5. Releases Tag Validation + +**Function**: `checkForReleases()` + +**Rules**: +- Every commit MUST have `Releases:` line +- Format: `Releases: main, 13.4, 12.4` (comma-separated) +- Valid values: `main`, version numbers like `13.4`, `12.4` + +**Regex**: `/^Releases: (main|[0-9]+\.[0-9])(, *(main|[0-9]+\.[0-9]))*$/` + +**Error Message**: +``` +You need a 'Releases:' line. For instance: Releases: main, 8.7 +``` + +**Location**: Line 227 in hook + +## Complete Validation Flow + +``` +Commit attempted + ↓ +1. Check line length (≤ 72 chars) + ↓ +2. Check commit type ([BUGFIX], etc.) + ↓ +3. Check Resolves/Fixes tag exists + ↓ +4. Check Releases tag exists + ↓ +All pass? → Add Change-Id → Commit succeeds +Any fail? → Show errors → Commit rejected +``` + +## Error Messages + +### Full Error Output + +When validation fails: +``` +------------------------------------------------------------------ + >> ERROR in your commit message: + + - The maximum line length of 72 characters is exceeded. + - You need at least one 'Resolves: #' line. + - You need a 'Releases:' line. For instance: Releases: main, 8.7 + + Please refer to [1] for details on the commit requirements. + You should fix this and then do commit --amend etc. + [1] https://docs.typo3.org/typo3cms/ContributionWorkflowGuide/latest/singlehtml/Index.html#commit-message-rules-for-typo3-cms +------------------------------------------------------------------ +``` + +### Individual Errors + +| Check | Error Message | +|-------|---------------| +| Line length | `The maximum line length of 72 characters is exceeded.` | +| Commit type | `Your first line has to contain a commit type like '[BUGFIX]'.` | +| Resolves tag | `You need at least one 'Resolves: #' line.` | +| Releases tag | `You need a 'Releases:' line. For instance: Releases: main, 8.7` | + +## Troubleshooting + +### Hook Not Running + +**Symptom**: Commits succeed without validation + +**Causes**: +1. Hook not installed +2. Hook not executable +3. Git hooks disabled + +**Solutions**: +```bash +# Check if hook exists +ls -la .git/hooks/commit-msg + +# Reinstall hook +composer gerrit:setup + +# Verify permissions +chmod +x .git/hooks/commit-msg + +# Check Git config (hooks disabled?) +git config --get core.hooksPath +``` + +### Hook Rejecting Valid Commit + +**Symptom**: Valid commit message rejected + +**Debug**: +```bash +# Test commit message manually +bash .git/hooks/commit-msg .git/COMMIT_EDITMSG + +# Check for hidden characters +cat -A .git/COMMIT_EDITMSG + +# Verify line endings (should be LF, not CRLF) +file .git/COMMIT_EDITMSG +``` + +**Common issues**: +- Windows line endings (CRLF) instead of Unix (LF) +- Trailing whitespace +- Non-ASCII characters in unexpected places +- Tabs vs spaces + +### Change-Id Not Generated + +**Symptom**: Commit succeeds but no Change-Id added + +**Causes**: +1. Change-Id already exists (manual addition) +2. Config disables it: `git config --get gerrit.createChangeId` returns `false` +3. fixup!/squash! commit (intentionally skipped) + +**Solutions**: +```bash +# Enable Change-Id generation +git config gerrit.createChangeId true + +# Re-commit to generate +git commit --amend --no-edit + +# Verify Change-Id added +git log -1 +``` + +### Multiple Change-Ids + +**Symptom**: Commit has multiple Change-Id lines + +**Impact**: Gerrit will reject or behave unexpectedly + +**Fix**: +```bash +# Edit commit message +git commit --amend + +# Remove duplicate Change-Id lines (keep only one) +# Save and exit +``` + +## Hook Customization + +### When to Customize + +**Valid reasons**: +- Project-specific validation rules +- Additional required tags +- Custom commit message format + +**Invalid reasons**: +- Bypassing validation (use `--no-verify` temporarily instead) +- Making validation more lenient (breaks standardization) + +### Safe Customization Pattern + +```bash +# 1. Fork the hook +cp .git/hooks/commit-msg .git/hooks/commit-msg.custom + +# 2. Add custom validation +# Edit .git/hooks/commit-msg.custom + +# 3. Call from main hook +# In .git/hooks/commit-msg, add: +# .git/hooks/commit-msg.custom "$1" + +# 4. Document customization +echo "Custom validation: " >> .git/hooks/commit-msg.custom +``` + +### Example: Additional Tag + +Add optional `Sponsored-by:` tag: + +```bash +# Add to checkForResolves() section +checkForSponsor() { + if grep -q -E '^Sponsored-by: ' "$MSG"; then + # Valid sponsor tag found + return 0 + fi +} + +# Call in validation sequence +checkForLineLength +checkForCommitType +checkForResolves +checkForReleases +checkForSponsor # Custom check +``` + +## Bypassing Hook + +### When to Bypass + +**Valid cases**: +- Emergency hotfixes +- Rebasing with preserved commits +- Importing historical commits +- Temporary testing + +**Invalid cases**: +- Avoiding fixing commit message +- Regular development workflow + +### How to Bypass + +```bash +# Single commit +git commit --no-verify + +# Amend without hook +git commit --amend --no-verify + +# Rebase without hook +GIT_EDITOR=true git rebase -i HEAD~5 --no-verify +``` + +**Warning**: Gerrit will still reject invalid commits! Bypassing hook locally doesn't bypass Gerrit validation. + +## Hook History + +### Version 1.1 (Current) + +**From**: TYPO3 CI Review 1.1 +**Based on**: Gerrit Code Review 2.14.6 + +**Changes from Gerrit original**: +- Added line length check (72 chars) +- Added commit type check ([BUGFIX], etc.) +- Added Resolves/Fixes check +- Added Releases check +- Modified Change-Id placement (after footer) + +### Proposed Version 1.2 (Issue #107881) + +**Change**: Update error message for Resolves check +- **Old**: `'Resolves|Fixes: #'` +- **New**: `'Resolves: #'` + +**Rationale**: +- TYPO3 standard is `Resolves:` only +- `Fixes:` accepted for backward compatibility only +- Error message should guide toward standard practice + +**Validation regex unchanged**: Still accepts both for compatibility + +## Hook Source Code Structure + +```bash +Build/git-hooks/commit-msg +├── License header (Apache 2.0) +├── TYPO3 changes documentation +├── add_ChangeId() function +│ ├── clean_message preprocessing +│ ├── Skip conditions (fixup, squash, existing) +│ ├── ID generation +│ └── AWK script for placement +├── _gen_ChangeId() helper +├── _gen_ChangeIdInput() helper +├── Validation functions: +│ ├── checkForLineLength() +│ ├── checkForCommitType() +│ ├── checkForResolves() +│ └── checkForReleases() +├── Validation execution +└── add_ChangeId() call +``` + +## Best Practices + +### For Contributors + +1. **Install hook early**: First thing after cloning +2. **Never bypass**: Fix messages instead of bypassing +3. **Don't fight the hook**: Learn requirements, follow them +4. **Use templates**: `git config commit.template ~/.gitmessage.txt` +5. **Test locally**: Use `scripts/validate-commit-message.py` + +### For Maintainers + +1. **Document changes**: Keep this reference updated +2. **Test thoroughly**: Validate changes don't break existing commits +3. **Backward compatible**: Keep regex accepting old patterns +4. **Clear errors**: Make error messages actionable +5. **Version carefully**: Changes affect all contributors + +## Related Files + +- `Build/git-hooks/commit-msg` - The hook itself +- `Build/git-hooks/pre-commit` - Code quality checks +- `assets/commit-template.txt` - Commit message template +- `scripts/validate-commit-message.py` - Offline validator +- `references/commit-message-format.md` - Commit message specification + +## References + +- **Hook Source**: https://github.com/TYPO3/typo3/blob/main/Build/git-hooks/commit-msg +- **Git Hooks Docs**: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks +- **Gerrit Hooks**: https://gerrit-review.googlesource.com/Documentation/cmd-hook-commit-msg.html +- **Issue #107881**: Standardize error message to mention only Resolves + +## Quick Reference + +| Validation | Required Format | Error if Missing | +|------------|----------------|------------------| +| Commit type | `[TYPE]` in first line | Yes | +| Line length | ≤ 72 characters | Yes | +| Resolves | `Resolves: #123` | Yes | +| Releases | `Releases: main` | Yes | +| Change-Id | Auto-generated | N/A (added by hook) | + +## See Also + +- `scripts/validate-commit-message.py` - Test messages offline +- `scripts/create-commit-message.py` - Generate compliant messages +- `assets/commit-template.txt` - Pre-filled template diff --git a/references/ddev-setup-workflow.md b/references/ddev-setup-workflow.md new file mode 100644 index 0000000..a98abfb --- /dev/null +++ b/references/ddev-setup-workflow.md @@ -0,0 +1,674 @@ +# TYPO3 Core Development - Complete DDEV Setup Workflow + +Production-tested workflow for setting up a complete TYPO3 Core development environment with DDEV. + +## Overview + +This workflow creates a fully functional TYPO3 Core development environment with: +- TYPO3 Core v14 (main branch) +- PHP 8.4 on Apache with FPM +- MariaDB 10.6 +- Test data and styleguide extensions +- Git configured for Gerrit submissions +- Ready for Core development and testing + +## Prerequisites + +**Required**: +- Git installed and configured +- DDEV installed (https://ddev.readthedocs.io/) +- SSH keys configured for GitHub and Gerrit + +**Verify DDEV**: +```bash +ddev version +# Should show DDEV version >= 1.21 +``` + +## Complete Setup Workflow + +### Step 1: Create Project Directory + +```bash +# Option A: Using 'take' (zsh/oh-my-zsh) +take t3coredev-14-php8-4 + +# Option B: Standard bash +mkdir -p t3coredev-14-php8-4 && cd t3coredev-14-php8-4 +``` + +**Note**: Use descriptive directory names indicating TYPO3 version and PHP version. + +### Step 2: Clone TYPO3 Core Repository + +```bash +# Clone from GitHub (faster than Gerrit for initial clone) +git clone git@github.com:typo3/typo3 . + +# Note: The dot (.) clones into current directory +``` + +### Step 3: Configure Git for TYPO3 Contributions + +```bash +# Set your identity +git config user.name "YOUR NAME" +git config user.email "YOUR@EMAIL" + +# Enable automatic rebase (required for TYPO3) +git config branch.autosetuprebase remote +``` + +### Step 4: Install Git Hooks + +```bash +# Copy commit-msg hook (adds Change-Id) +cp Build/git-hooks/commit-msg .git/hooks/commit-msg + +# Alternative: Use composer command +# composer gerrit:setup +``` + +### Step 5: Configure Gerrit Remote + +```bash +# Set Gerrit as push destination +git config remote.origin.pushurl ssh://YOURT3OUSERNAME@review.typo3.org:29418/Packages/TYPO3.CMS.git + +# Configure push refspec for Gerrit review +git config remote.origin.push +refs/heads/main:refs/for/main +``` + +**Important**: Replace `YOURT3OUSERNAME` with your actual Gerrit username! + +### Step 6: Configure DDEV Project + +```bash +# Set project type to TYPO3 +ddev config --project-type typo3 -y + +# Configure timezone (adjust to your location) +ddev config --timezone "Europe/Vienna" + +# Set PHP version for v14 development +ddev config --php-version=8.4 + +# Use Apache with FPM (recommended for Core dev) +ddev config --webserver-type=apache-fpm + +# Set MariaDB version +ddev config --database=mariadb:10.6 +``` + +**PHP Version Notes**: +- TYPO3 v14: PHP 8.2, 8.3, 8.4 +- TYPO3 v13: PHP 8.1, 8.2, 8.3 +- Check `composer.json` for exact requirements + +### Step 7: Configure DDEV Environment Variables + +```bash +# Set TYPO3 context to Development/Ddev +ddev config --web-environment-add="TYPO3_CONTEXT=Development/Ddev" + +# Set Composer root version for dev branch +ddev config --web-environment-add="COMPOSER_ROOT_VERSION=14.0.x-dev" +``` + +**Context Meanings**: +- `Development/Ddev`: Enables debugging, disables caching +- `Production`: Live site configuration +- `Testing`: For automated test environments + +### Step 8: Start DDEV + +```bash +ddev start +``` + +**What happens**: +1. Creates Docker containers (web, db, phpmyadmin) +2. Configures networking +3. Sets up SSL certificates +4. Mounts project directory + +**Expected output**: +``` +Starting t3coredev-14-php8-4... +Successfully started t3coredev-14-php8-4 +Project can be reached at https://t3coredev-14-php8-4.ddev.site +``` + +### Step 9: Install Dependencies + +```bash +# Use TYPO3's runTests.sh script (preferred for Core dev) +./Build/Scripts/runTests.sh -s composerInstall + +# Alternative: Direct composer command +# ddev composer install +``` + +**Why runTests.sh?** +- Ensures correct Composer flags +- Consistent with CI environment +- Handles Core-specific requirements + +### Step 10: Prepare TYPO3 Installation + +```bash +# Create installation trigger file +ddev exec 'touch /var/www/html/FIRST_INSTALL' + +# Enable Install Tool +ddev exec 'touch /var/www/html/typo3conf/ENABLE_INSTALL_TOOL' +ddev exec 'echo "KEEP_FILE" > /var/www/html/typo3conf/ENABLE_INSTALL_TOOL' +``` + +**File purposes**: +- `FIRST_INSTALL`: Triggers installation wizard +- `ENABLE_INSTALL_TOOL`: Enables Install Tool access (with KEEP_FILE prevents auto-deletion) + +### Step 11: Run TYPO3 Setup + +```bash +ddev typo3 setup \ + --driver=mysqli \ + --host=db \ + --port=3306 \ + --dbname=db \ + --username=db \ + --password=db \ + --admin-username=backenduser \ + --admin-user-password='YOUR_SECURE_PASSWORD' \ + --admin-email='YOUR@EMAIL' \ + --project-name='TYPO3 Core Dev v14 PHP 8.4' \ + --no-interaction \ + --server-type=apache \ + --force +``` + +**Important**: +- Replace `YOUR_SECURE_PASSWORD` with your preferred admin password +- Replace `YOUR@EMAIL` with your email +- Database credentials (db/db/db) are DDEV defaults + +**What this creates**: +- Database tables and schema +- Backend admin user account +- Basic TYPO3 configuration +- AdditionalConfiguration.php + +### Step 12: Activate Core Extensions + +```bash +# Set up extensions first +ddev typo3 extension:setup + +# Activate indexed_search (relevant for testing search functionality) +ddev typo3 extension:activate indexed_search + +# Activate styleguide (provides test data and UI components) +ddev typo3 extension:activate styleguide + +# Activate scheduler (for scheduled tasks) +ddev typo3 extension:activate scheduler +``` + +**Extension purposes**: +- `indexed_search`: Full-text search (relevant to bug #105737!) +- `styleguide`: Test data generator, UI component showcase +- `scheduler`: Cron-like task scheduling + +### Step 13: Configure Backend User Groups + +```bash +ddev typo3 setup:begroups:default --groups=Both +``` + +**Creates**: +- Editor group (content management) +- Advanced Editor group (extended permissions) +- Assigns both groups to admin user + +### Step 14: Generate Test Data + +```bash +# Generate TCA (Table Configuration Array) examples +ddev typo3 styleguide:generate --create -- tca + +# Generate frontend system template +ddev typo3 styleguide:generate --create -- frontend-systemplate +``` + +**Test data includes**: +- All TCA field types with examples +- Content elements with various configurations +- Pages with different properties +- Frontend templates and TypoScript + +### Step 15: Launch TYPO3 Backend + +```bash +ddev launch /typo3 +``` + +Opens TYPO3 backend in your default browser. + +**Login credentials**: +- Username: `backenduser` +- Password: Whatever you set in Step 11 + +## Post-Setup Verification + +### Verify Installation + +**Check TYPO3 is running**: +```bash +ddev launch +``` + +**Access Install Tool**: +```bash +ddev launch /typo3/install.php +``` + +**View site info**: +```bash +ddev describe +``` + +### Verify Git Configuration + +```bash +# Check user config +git config user.name +git config user.email + +# Check Gerrit config +git config remote.origin.pushurl +git config remote.origin.push + +# Verify hooks +ls -la .git/hooks/commit-msg +``` + +### Verify DDEV Configuration + +```bash +# View DDEV config +cat .ddev/config.yaml + +# Should show: +# - project_type: typo3 +# - php_version: "8.4" +# - webserver_type: apache-fpm +# - database: mariadb:10.6 +# - web_environment: +# - TYPO3_CONTEXT=Development/Ddev +# - COMPOSER_ROOT_VERSION=14.0.x-dev +``` + +### Test Core Functionality + +**Access frontend**: +```bash +ddev launch +``` + +**Run tests**: +```bash +# Unit tests +./Build/Scripts/runTests.sh -s unit + +# Functional tests +./Build/Scripts/runTests.sh -s functional + +# Check available test suites +./Build/Scripts/runTests.sh -h +``` + +## Development Workflow + +### Creating a Feature Branch + +```bash +# Ensure main is up-to-date +git checkout main +git pull origin main + +# Create feature branch +git checkout -b feature/105737-fix-indexed-search-crash +``` + +### Making Changes + +```bash +# Make code changes +vim typo3/sysext/indexed_search/Classes/Indexer.php + +# Stage changes +git add . + +# Commit with proper message +git commit +# (Use commit message template) +``` + +### Testing Changes + +```bash +# Run relevant tests +./Build/Scripts/runTests.sh -s unit -- \ + typo3/sysext/indexed_search/Tests/Unit/ + +# Check code style +./Build/Scripts/runTests.sh -s cgl -n +``` + +### Submitting to Gerrit + +```bash +# Push to Gerrit for review +git push origin HEAD:refs/for/main +``` + +## Useful DDEV Commands + +### Project Management + +```bash +# Start project +ddev start + +# Stop project +ddev stop + +# Restart project +ddev restart + +# Delete project (keeps files) +ddev delete + +# Power off all DDEV projects +ddev poweroff +``` + +### Database Management + +```bash +# Export database +ddev export-db --file=backup.sql.gz + +# Import database +ddev import-db --file=backup.sql.gz + +# Access database CLI +ddev mysql + +# Launch phpMyAdmin +ddev launch -p +``` + +### TYPO3 Commands + +```bash +# Clear all caches +ddev typo3 cache:flush + +# Clear specific cache +ddev typo3 cache:flush --group=system + +# Run scheduler tasks +ddev typo3 scheduler:run + +# List available commands +ddev typo3 list +``` + +### Debugging + +```bash +# View logs +ddev logs + +# Follow logs (like tail -f) +ddev logs -f + +# SSH into container +ddev ssh + +# Execute command in container +ddev exec 'command' +``` + +### Performance + +```bash +# View resource usage +docker stats + +# Restart services if slow +ddev restart +``` + +## Customization Options + +### Different PHP Versions + +```bash +# Switch to PHP 8.2 +ddev config --php-version=8.2 +ddev restart +``` + +### Different Database Versions + +```bash +# Use MySQL instead of MariaDB +ddev config --database=mysql:8.0 +ddev restart +``` + +### Additional Services + +```bash +# Add Redis +ddev get ddev/ddev-redis + +# Add Elasticsearch +ddev get ddev/ddev-elasticsearch + +# Add Mailhog (email testing) +ddev config --mailhog-port=8026 +``` + +### Custom Domain + +```bash +# Add additional hostname +ddev config --additional-hostnames=t3dev.local +ddev restart +``` + +## Troubleshooting + +### "Port already allocated" + +**Problem**: DDEV can't start because ports are in use + +**Solution**: +```bash +# Stop other DDEV projects +ddev poweroff + +# Or change port +ddev config --router-http-port=8080 --router-https-port=8443 +``` + +### "Composer timeout" + +**Problem**: Composer operations timeout + +**Solution**: +```bash +# Increase timeout +ddev composer config --global process-timeout 2000 + +# Or use runTests.sh +./Build/Scripts/runTests.sh -s composerInstall +``` + +### "Cannot write to directory" + +**Problem**: Permission issues in container + +**Solution**: +```bash +# Fix permissions +ddev exec 'chmod -R 777 var/ typo3temp/ typo3conf/' + +# Or restart DDEV +ddev restart +``` + +### "Database connection failed" + +**Problem**: TYPO3 can't connect to database + +**Solution**: +```bash +# Check database is running +ddev describe + +# Verify credentials in LocalConfiguration.php +ddev exec 'cat typo3conf/LocalConfiguration.php | grep -A5 DB' + +# Should show: host=db, username=db, password=db, database=db +``` + +## Best Practices + +### Directory Naming + +Use descriptive names indicating: +- TYPO3 version: `t3coredev-14` +- PHP version: `php8-4` +- Purpose: `coredev`, `testing`, `feature-name` + +Examples: +- `t3coredev-14-php8-4` +- `t3-bugfix-105737` +- `t3-testing-indexed-search` + +### Git Workflow + +1. **Always start from main**: + ```bash + git checkout main + git pull origin main + ``` + +2. **Use feature branches**: + ```bash + git checkout -b feature/issue-description + ``` + +3. **Keep single commit per patch**: + ```bash + git commit --amend # Update existing commit + ``` + +4. **Rebase regularly**: + ```bash + git fetch origin + git rebase origin/main + ``` + +### DDEV Management + +1. **Stop unused projects**: + ```bash + ddev list + ddev stop + ``` + +2. **Clean up old projects**: + ```bash + ddev delete + # Then manually delete directory + ``` + +3. **Monitor resources**: + ```bash + docker stats + ``` + +### Testing Workflow + +1. **Test before committing**: + ```bash + ./Build/Scripts/runTests.sh -s unit + ./Build/Scripts/runTests.sh -s functional + ``` + +2. **Check code style**: + ```bash + ./Build/Scripts/runTests.sh -s cgl -n + ``` + +3. **Fix code style automatically**: + ```bash + ./Build/Scripts/runTests.sh -s cgl + ``` + +## Quick Reference + +### Essential Commands + +| Task | Command | +|------|---------| +| Start DDEV | `ddev start` | +| Stop DDEV | `ddev stop` | +| Open backend | `ddev launch /typo3` | +| Clear cache | `ddev typo3 cache:flush` | +| Run unit tests | `./Build/Scripts/runTests.sh -s unit` | +| Install composer | `./Build/Scripts/runTests.sh -s composerInstall` | +| View logs | `ddev logs -f` | +| SSH into container | `ddev ssh` | +| Export database | `ddev export-db --file=backup.sql.gz` | +| Git push to Gerrit | `git push origin HEAD:refs/for/main` | + +### TYPO3 Versions & PHP Compatibility + +| TYPO3 Version | PHP Versions | Branch | Status | +|---------------|--------------|--------|--------| +| v14 (main) | 8.2, 8.3, 8.4 | main | Development | +| v13 (LTS) | 8.1, 8.2, 8.3 | 13.4 | Active | +| v12 (ELTS) | 8.1, 8.2 | 12.4 | Security only | + +### Default Credentials + +| Service | URL | Username | Password | +|---------|-----|----------|----------| +| Backend | `https://[project].ddev.site/typo3` | backenduser | (your choice) | +| Database | `db:3306` | db | db | +| phpMyAdmin | `https://[project].ddev.site:8037` | db | db | + +## Integration with typo3-ddev-skill + +This workflow complements the `typo3-ddev-skill`: +- Use `typo3-ddev-skill` for quick setup automation +- Use this workflow for manual step-by-step understanding +- Both produce equivalent development environments + +## Additional Resources + +- **DDEV Documentation**: https://ddev.readthedocs.io/ +- **TYPO3 Development**: https://docs.typo3.org/m/typo3/reference-coreapi/ +- **runTests.sh Guide**: https://docs.typo3.org/m/typo3/guide-contributionworkflow/main/en-us/Testing/ +- **TYPO3 Slack**: https://typo3.slack.com (#typo3-cms-coredev) + +--- + +**Note**: This workflow is based on proven production usage and is continuously updated for current TYPO3 versions. Always check official documentation for the latest recommendations. diff --git a/references/forge-api.md b/references/forge-api.md new file mode 100644 index 0000000..6e11116 --- /dev/null +++ b/references/forge-api.md @@ -0,0 +1,436 @@ +# Forge REST API Documentation + +Complete guide to using the TYPO3 Forge (Redmine) REST API for programmatic issue management. + +## Overview + +TYPO3 Forge (https://forge.typo3.org) is built on Redmine and exposes a REST API for: +- Creating issues +- Updating issues +- Querying project metadata +- Managing issue relationships + +## Authentication + +### Get API Key + +1. Log in to https://forge.typo3.org +2. Go to https://forge.typo3.org/my/account +3. Find "API access key" on the right side +4. Click "Show" to reveal your key +5. Store securely (treat like a password!) + +### Using API Key + +Pass via HTTP header: +```bash +-H "X-Redmine-API-Key: your-api-key-here" +``` + +**Security**: Never commit API keys to repositories. Use environment variables: +```bash +export FORGE_API_KEY="your-api-key-here" +``` + +## Base URL + +All API endpoints use: +``` +https://forge.typo3.org +``` + +## Common Endpoints + +### Create Issue + +**Endpoint**: `POST /issues.json` + +**Request**: +```bash +curl -X POST \ + -H "Content-Type: application/json" \ + -H "X-Redmine-API-Key: $FORGE_API_KEY" \ + -d '{ + "issue": { + "project_id": "typo3cms-core", + "subject": "Issue title here", + "description": "Detailed description", + "tracker_id": 1, + "category_id": 975, + "priority_id": 4, + "custom_fields": [ + {"id": 4, "value": "13"} + ] + } + }' \ + https://forge.typo3.org/issues.json +``` + +**Response**: +```json +{ + "issue": { + "id": 107881, + "project": {"id": 27, "name": "TYPO3 Core"}, + "tracker": {"id": 1, "name": "Bug"}, + "status": {"id": 1, "name": "New"}, + "priority": {"id": 4, "name": "Should have"}, + "subject": "Issue title here", + "description": "Detailed description", + "created_on": "2024-12-15T10:30:00Z", + "updated_on": "2024-12-15T10:30:00Z" + } +} +``` + +**Extract Issue Number**: +```bash +# Parse with jq +curl ... | jq -r '.issue.id' + +# Parse with grep +curl ... | grep -oP '"id":\K[0-9]+' | head -1 +``` + +### Get Project Metadata + +**Endpoint**: `GET /projects/typo3cms-core.json` + +**Request**: +```bash +curl -H "X-Redmine-API-Key: $FORGE_API_KEY" \ + https://forge.typo3.org/projects/typo3cms-core.json +``` + +**Response includes**: +- Available trackers (Bug, Feature, Task, etc.) +- Issue categories (Backend, Frontend, etc.) +- Custom field definitions + +### Get Issue Details + +**Endpoint**: `GET /issues/{id}.json` + +**Request**: +```bash +curl -H "X-Redmine-API-Key: $FORGE_API_KEY" \ + https://forge.typo3.org/issues/105737.json +``` + +**Response includes**: +- Full issue details +- Custom fields +- Status and assignments +- Related issues + +## Field IDs + +### Trackers + +| ID | Name | +|----|------| +| 1 | Bug | +| 2 | Feature | +| 4 | Task | +| 6 | Story | +| 10 | Epic | + +### Priorities + +| ID | Name | +|----|------| +| 2 | Nice to have | +| 3 | Must have | +| 4 | Should have | +| 5 | Could have | + +### Common Categories + +| ID | Name | +|------|------| +| 971 | Backend API | +| 972 | Backend User Interface | +| 973 | Caching | +| 974 | Database API (Doctrine DBAL) | +| 975 | Miscellaneous | +| 976 | Extension Manager | +| 977 | Frontend | +| 1000 | Indexed Search | +| 1003 | Content Rendering | +| 1004 | Documentation | + +**Get full list**: Use `scripts/query-forge-metadata.sh` + +### Custom Fields + +| ID | Name | Purpose | +|----|------|---------| +| 3 | Tags | Comma-separated keywords | +| 4 | TYPO3 Version | Version affected (e.g., "13", "12") | +| 5 | PHP Version | PHP version (e.g., "8.2", "8.3") | +| 8 | Complexity | Complexity estimate | +| 15 | Is Regression | Whether it's a regression | +| 18 | Sprint Focus | Sprint assignment | + +## Complete Examples + +### Example 1: Create Bug Report + +```bash +export FORGE_API_KEY="your-api-key-here" + +curl -X POST \ + -H "Content-Type: application/json" \ + -H "X-Redmine-API-Key: $FORGE_API_KEY" \ + -d '{ + "issue": { + "project_id": "typo3cms-core", + "subject": "Indexed search causes crash on malformed UTF-8", + "description": "When processing content with malformed UTF-8, the indexed search indexer crashes with TypeError in PHP 8.2+.\n\nSteps to reproduce:\n1. Create page with malformed UTF-8 content\n2. Run indexer\n3. Observe crash\n\nExpected: Graceful handling\nActual: TypeError exception", + "tracker_id": 1, + "category_id": 1000, + "priority_id": 4, + "custom_fields": [ + {"id": 4, "value": "13"}, + {"id": 5, "value": "8.2"}, + {"id": 3, "value": "indexed search, UTF-8, crash"} + ] + } + }' \ + https://forge.typo3.org/issues.json +``` + +### Example 2: Create Feature Request + +```bash +curl -X POST \ + -H "Content-Type: application/json" \ + -H "X-Redmine-API-Key: $FORGE_API_KEY" \ + -d '{ + "issue": { + "project_id": "typo3cms-core", + "subject": "Add WebP image format support", + "description": "Add native WebP support to TYPO3 image processing:\n\n- WebP MIME type detection\n- Image manipulation support\n- Configuration options\n\nBenefit: 25-30% better compression than JPEG", + "tracker_id": 2, + "category_id": 977, + "priority_id": 5, + "custom_fields": [ + {"id": 4, "value": "14"}, + {"id": 3, "value": "WebP, images, performance"} + ] + } + }' \ + https://forge.typo3.org/issues.json +``` + +### Example 3: Create Task + +```bash +curl -X POST \ + -H "Content-Type: application/json" \ + -H "X-Redmine-API-Key: $FORGE_API_KEY" \ + -d '{ + "issue": { + "project_id": "typo3cms-core", + "subject": "Standardize commit-msg hook error message", + "description": "Update Build/git-hooks/commit-msg error message to mention only '\''Resolves:'\'' tag instead of '\''Resolves|Fixes:'\'' to align with TYPO3 community standard.\n\nWhile validation regex accepts both for backward compatibility, error message should guide toward single standard keyword.", + "tracker_id": 4, + "category_id": 975, + "priority_id": 4, + "custom_fields": [ + {"id": 4, "value": "14"} + ] + } + }' \ + https://forge.typo3.org/issues.json +``` + +## Error Handling + +### Common Errors + +**422 Unprocessable Entity**: +```json +{ + "errors": ["Category is not included in the list"] +} +``` + +**Solution**: Check field IDs are valid for the project + +**422 - Required Field Missing**: +```json +{ + "errors": ["Typo3 version cannot be blank"] +} +``` + +**Solution**: Add required custom field (id: 4 for TYPO3 version) + +**401 Unauthorized**: +``` +{"errors": ["You are not authorized to access this page."]} +``` + +**Solution**: Check API key is correct and has permissions + +### Validation + +Before creating issue, validate: +- [ ] API key is set and valid +- [ ] project_id is "typo3cms-core" +- [ ] subject is descriptive (not too generic) +- [ ] tracker_id is valid (1, 2, or 4 most common) +- [ ] category_id matches project categories +- [ ] TYPO3 version custom field included (id: 4) + +## Best Practices + +### Subject Lines + +✅ **Good**: +- "Indexed search crashes on malformed UTF-8" +- "Add WebP image format support" +- "Standardize commit-msg hook error message" + +❌ **Bad**: +- "Fix bug" +- "Improvement needed" +- "Question about feature" + +### Descriptions + +**Structure**: +1. Brief summary (what is the issue) +2. Steps to reproduce (for bugs) +3. Expected behavior +4. Actual behavior +5. Additional context + +**Include**: +- Error messages +- Stack traces +- Version information +- Configuration details + +**Avoid**: +- Asking questions (use Slack instead) +- Multiple unrelated issues in one ticket +- Vague descriptions without details + +### Categories + +Choose most specific category: +- Not "Miscellaneous" if more specific exists +- "Backend API" for backend PHP code +- "Backend User Interface" for backend UI/UX +- "Frontend" for frontend rendering +- Component-specific for extensions (e.g., "Indexed Search") + +### Priority + +**Guidelines**: +- **Must have (3)**: Blocking issues, critical bugs, security +- **Should have (4)**: Normal bugs, important features (most common) +- **Could have (5)**: Nice-to-have features, minor improvements +- **Nice to have (2)**: Low priority, future considerations + +## Automation Tips + +### Store Issue Template + +```bash +cat > /tmp/issue-template.json <<'EOF' +{ + "issue": { + "project_id": "typo3cms-core", + "subject": "", + "description": "", + "tracker_id": 1, + "category_id": 975, + "priority_id": 4, + "custom_fields": [ + {"id": 4, "value": "13"} + ] + } +} +EOF +``` + +### Parse Response + +```bash +# Extract issue number +ISSUE_ID=$(curl ... | jq -r '.issue.id') + +# Build URL +ISSUE_URL="https://forge.typo3.org/issues/${ISSUE_ID}" + +# Use in commit message +echo "Resolves: #${ISSUE_ID}" +``` + +### Batch Operations + +Query multiple issues: +```bash +for id in 105737 107881 108000; do + curl -H "X-Redmine-API-Key: $FORGE_API_KEY" \ + "https://forge.typo3.org/issues/${id}.json" +done +``` + +## Integration with Git + +### Create Issue and Commit + +```bash +#!/bin/bash +# Create issue +RESPONSE=$(curl -s -X POST \ + -H "Content-Type: application/json" \ + -H "X-Redmine-API-Key: $FORGE_API_KEY" \ + -d @issue.json \ + https://forge.typo3.org/issues.json) + +# Extract issue number +ISSUE_ID=$(echo "$RESPONSE" | jq -r '.issue.id') + +# Use in commit +git commit -m "[BUGFIX] Fix the problem + +Resolves: #${ISSUE_ID} +Releases: main" +``` + +### Link Gerrit Patch to Issue + +After submitting to Gerrit: +```bash +GERRIT_URL="https://review.typo3.org/c/Packages/TYPO3.CMS/+/91302" +# Add comment to Forge issue with patch link +# (requires additional API call - see Redmine API docs) +``` + +## Resources + +- **Redmine API Docs**: https://www.redmine.org/projects/redmine/wiki/Rest_api +- **TYPO3 Forge**: https://forge.typo3.org +- **API Access Key**: https://forge.typo3.org/my/account +- **Project Info**: https://forge.typo3.org/projects/typo3cms-core + +## Quick Reference + +| Task | Endpoint | Method | +|------|----------|--------| +| Create issue | `/issues.json` | POST | +| Get issue | `/issues/{id}.json` | GET | +| Update issue | `/issues/{id}.json` | PUT | +| Get project | `/projects/{id}.json` | GET | +| List issues | `/issues.json?project_id=typo3cms-core` | GET | + +## See Also + +- `scripts/create-forge-issue.sh` - Interactive issue creation +- `scripts/query-forge-metadata.sh` - Query project metadata +- `references/commit-message-format.md` - For using issue numbers in commits diff --git a/references/gerrit-review-patterns.md b/references/gerrit-review-patterns.md new file mode 100644 index 0000000..be3d6d5 --- /dev/null +++ b/references/gerrit-review-patterns.md @@ -0,0 +1,386 @@ +# TYPO3 Gerrit Review Patterns - Real-World Insights + +Based on analysis of actual merged patches from review.typo3.org, this document captures common review patterns, expectations, and best practices. + +## Understanding Revision Counts + +**Key Insight**: High revision counts (7-25 patch sets) are NORMAL and expected, not a sign of failure. + +**Real Examples**: +- Change #90226: 24 patch sets (functional tests for Extbase FileUpload) +- Change #88519: 14 patch sets (breaking change - Record API) +- Change #91161: 9 patch sets (DI refactoring) +- Change #91284: 7 patch sets (pagetree performance) + +**What causes multiple revisions**: +1. CI failures requiring fixes +2. Rebases due to base branch updates +3. Code quality refinements based on reviewer feedback +4. Architectural improvements suggested by core team +5. Edge case handling +6. Scope adjustments (e.g., backport constraints) + +**Mindset**: Each revision makes the patch better. Multiple revisions show: +- Responsiveness to feedback +- Iterative improvement +- Collaboration with core team +- Thorough vetting process + +## Common Reviewer Feedback Themes + +### 1. Architectural Alignment + +**Pattern**: Leverage framework patterns over custom solutions + +**Example from #91161**: +``` +Reviewer: "Just make this method no-op with only the trigger_error() and +remove $this->instances since the service locator will catch classes that +implements the interface automatically." +``` + +**Expectation**: +- Use dependency injection (DI) over manual instance management +- Leverage service locators for interface-based registration +- Follow TYPO3 framework patterns +- Avoid reinventing framework capabilities + +**Best Practice**: Before implementing, check if TYPO3 framework already provides the pattern. + +### 2. Configuration Best Practices + +**Pattern**: Services.yaml configuration matters + +**Example from #90226**: +``` +Reviewer: "Why is Domain/Validator/ excluded here? This would prevent +validators from receiving dependency injection." +``` + +**Expectation**: +- Understand Services.yaml exclusion patterns +- Don't copy boilerplate without understanding +- Enable DI for all appropriate classes +- Reference official documentation for patterns + +**Best Practice**: Review Services.yaml carefully, don't blindly copy from examples. + +### 3. Performance Validation + +**Pattern**: Performance claims require empirical evidence + +**Example from #91284**: +``` +Reviewer: "It performs much better. If a large number of pages are open, +there is still a very slight delay (milliseconds), but this should not +cause any problems." + +Reviewer: "Nice one here, removing the expensive calls to this.nodes.find() +- reduced from O(n^(m²)) [30ms] to O(n) [2-3ms]" +``` + +**Expectation**: +- Test performance fixes in production-like environments +- Provide computational complexity analysis +- Measure actual performance improvements +- Document before/after metrics +- Multiple reviewers test independently + +**Best Practice**: Include performance measurements in commit message or comments. + +### 4. Breaking Changes Documentation + +**Pattern**: Breaking changes need explicit communication + +**Example from #88519**: +``` +Reviewer: "The info that the item.record is now a record object, is +important to know for externals." + +Reviewer: "That's breaking IMHO" (regarding API change) +``` + +**Expectation**: +- Document API changes affecting extension developers +- Use `[!!!]` prefix for breaking changes +- Add deprecations with `trigger_error()` for BC breaks +- Consider backport constraints (may limit to main branch) +- Provide migration examples + +**Best Practice**: Always think about extension developers when changing public APIs. + +### 5. Code Quality Standards + +**Pattern**: Modern PHP practices and clean code + +**Recurring feedback themes**: +- Use named arguments in function calls +- Separate concerns (split large functions into classes) +- Improve readability through refactoring +- Handle edge cases explicitly +- Remove unused code + +**Best Practice**: Follow PSR-12 and modern PHP 8+ features. + +### 6. Test Stability Focus + +**Pattern**: Tests serve as API stability monitors + +**Example from #90226**: +``` +Reviewer: "These tests could serve as an important whistleblower with +extbase to monitor API stability and how frequently changes are needed." +``` + +**Expectation**: +- Tests should catch unintended API changes +- Test scope should be "as simple as possible and as complex as needed" +- Functional tests preferred over unit tests for integration points +- Tests validate real-world usage patterns + +**Best Practice**: Write tests that detect breaking changes, not just code coverage. + +### 7. Iterative Refinement Philosophy + +**Pattern**: Patches improve through collaboration, not rejection + +**Observed patterns**: +- Positive language: "I like! 🙌", "Awesome job!", "Nice one here" +- Constructive suggestions: "You could...", "Consider...", "What about..." +- Collaborative problem-solving: Multiple reviewers contribute ideas +- Incremental improvements: Each revision refines the approach + +**Expectation**: +- Be responsive to feedback +- Implement suggested improvements +- Ask clarifying questions when needed +- Iterate toward excellence + +**Best Practice**: View reviews as mentoring, not gatekeeping. + +## Common Revision Patterns + +### Pattern 1: CI Failure Cycle + +**Typical flow**: +1. Initial submission +2. CI rejects (CGL, PHPStan, tests) +3. Fix CI issues +4. Resubmit +5. New CI issues found +6. Repeat until green + +**Prevention**: Use typo3-conformance-skill and typo3-testing-skill BEFORE first submission. + +### Pattern 2: Rebase Cycle + +**Typical flow**: +1. Patch submitted +2. Base branch updated with other changes +3. Gerrit shows "needs rebase" +4. Rebase on latest main +5. Resolve conflicts +6. CI runs again (may reveal new issues) +7. Repeat as needed + +**Prevention**: Rebase regularly during development, not just at submission. + +### Pattern 3: Scope Adjustment + +**Typical flow**: +1. Patch targets main + version branches +2. Review reveals backport complexity +3. Dependencies on other changes discovered +4. Scope changed to "main only" +5. Commit message updated + +**Prevention**: Check dependencies before claiming backport compatibility. + +### Pattern 4: Architecture Refinement + +**Typical flow**: +1. Working implementation submitted +2. Reviewer suggests better framework pattern +3. Refactor to use framework capabilities +4. Simplify code by removing custom logic +5. May take 3-5 revisions to align + +**Prevention**: Study framework patterns before implementing custom solutions. + +## Review Timeline Expectations + +Based on analyzed patches: + +**Simple changes** (1-3 files, no breaking changes): +- Review starts: Within 1-2 days +- First feedback: 2-3 days +- Typical revisions: 2-5 patch sets +- Merge time: 1-2 weeks + +**Complex changes** (multiple files, new features): +- Review starts: Within 3-5 days +- First feedback: 3-7 days +- Typical revisions: 7-15 patch sets +- Merge time: 2-4 weeks + +**Breaking changes** (API changes, [!!!]): +- Review starts: Within 1-2 days +- First feedback: 1-3 days (architectural concerns raised early) +- Typical revisions: 10-20 patch sets +- Merge time: 3-6 weeks (due to documentation, deprecation) + +**Performance fixes**: +- Review starts: Within 1-2 days +- Testing phase: 1-2 weeks (reviewers test in production) +- Typical revisions: 5-10 patch sets +- Merge time: 2-3 weeks + +## Key Reviewers and Their Focus Areas + +Based on observed patterns: + +**Christian Kuhn (lolli)**: +- Architectural alignment +- Framework pattern usage +- Test quality and coverage +- Long-term maintainability + +**Benni Mack**: +- Breaking change implications +- Extension developer impact +- API design +- Documentation completeness + +**Stefan Bürk**: +- Configuration best practices +- Services.yaml patterns +- Dependency injection +- Code quality standards + +**Pattern**: Different reviewers have different expertise areas. Address each reviewer's specific concerns. + +## Best Practices from Real Reviews + +### Do's + +✅ **Respond to every comment**: Even if just "Done" or "Fixed in PS X" +✅ **Test in production-like environments**: Especially for performance fixes +✅ **Use framework patterns**: DI, service locators, event dispatchers +✅ **Document breaking changes**: Think about extension developers +✅ **Iterate based on feedback**: Don't defend, improve +✅ **Keep scope focused**: Don't expand scope during review +✅ **Update commit messages**: Reflect scope or approach changes +✅ **Add deprecations properly**: Use trigger_error() for BC breaks + +### Don'ts + +❌ **Don't take high revision counts personally**: They're normal and expected +❌ **Don't copy boilerplate blindly**: Understand configuration patterns +❌ **Don't skip testing**: CI will catch it anyway +❌ **Don't ignore architectural feedback**: Core team guides for good reasons +❌ **Don't rush rebases**: Test after rebasing +❌ **Don't claim performance without metrics**: Provide evidence +❌ **Don't break APIs without [!!!]**: Use proper prefixes +❌ **Don't argue with multiple reviewers**: If 2+ reviewers agree, they're probably right + +## Handling Common Situations + +### Situation 1: "My patch has 10 revisions already" + +**Response**: This is normal! Changes #90226 had 24, #88519 had 14. Keep iterating. + +**Action**: +1. Review all outstanding comments +2. Address each systematically +3. Test thoroughly after each change +4. Mark comments as resolved with explanation +5. Keep positive attitude + +### Situation 2: "Reviewer suggested complete refactoring" + +**Response**: Core team is guiding toward better patterns. This is mentoring. + +**Action**: +1. Ask clarifying questions if needed +2. Study the suggested pattern +3. Implement as suggested +4. Don't defend original approach +5. Learn framework patterns for future + +### Situation 3: "CI keeps failing after fixes" + +**Response**: Each rebase can reveal new issues. This is expected. + +**Action**: +1. Use typo3-conformance-skill locally +2. Use typo3-testing-skill for test failures +3. Validate BEFORE pushing +4. Consider environment differences +5. Ask for help if stuck + +### Situation 4: "Scope changed from 'main + 13.4' to 'main only'" + +**Response**: Backport complexity discovered during review. Common pattern. + +**Action**: +1. Update commit message (Releases: main) +2. Update Forge issue target version +3. Don't argue - backporting is complex +4. Focus on getting main merged first +5. Backport can be separate patch later + +## Learning from Reviews + +### What to Extract from Reviews + +When reading other reviews: +1. **Architectural patterns**: How do they structure code? +2. **Framework usage**: What TYPO3 APIs do they leverage? +3. **Testing approaches**: How do they test complex scenarios? +4. **Documentation style**: How do they explain breaking changes? +5. **Reviewer priorities**: What concerns get raised most? + +### How to Improve + +Based on review patterns: +1. **Study merged patches**: See what passes review +2. **Read reviewer comments**: Learn what matters to core team +3. **Use framework patterns**: Follow existing approaches +4. **Test thoroughly**: Validate locally before submission +5. **Be responsive**: Quick turnaround on feedback +6. **Stay positive**: Reviews are mentoring, not rejection + +## Summary: Review Success Pattern + +**Before submission**: +- ✅ Use typo3-conformance-skill +- ✅ Use typo3-testing-skill +- ✅ Study framework patterns +- ✅ Check Services.yaml configuration +- ✅ Test in realistic environment + +**During review**: +- ✅ Respond to all comments promptly +- ✅ Implement suggestions positively +- ✅ Test after each revision +- ✅ Update commit message as needed +- ✅ Ask questions when unclear + +**Mindset**: +- ✅ Multiple revisions are normal and healthy +- ✅ Reviews improve your code +- ✅ Core team is mentoring you +- ✅ Each iteration makes TYPO3 better +- ✅ You're learning framework patterns + +## References + +**Analyzed patches**: +- #90226: Extbase FileUpload functional tests (24 PS) +- #91161: DI in ExtractorService (9 PS) +- #91284: Pagetree performance (7 PS) +- #88519: Record API breaking change (14 PS) + +**Review platform**: https://review.typo3.org + +**Remember**: The best contributors don't have the fewest revisions - they have the most responsive and collaborative review interactions. diff --git a/references/gerrit-workflow.md b/references/gerrit-workflow.md new file mode 100644 index 0000000..35290e6 --- /dev/null +++ b/references/gerrit-workflow.md @@ -0,0 +1,783 @@ +# TYPO3 Gerrit Workflow Guide + +Comprehensive guide for working with Gerrit code review system in TYPO3 Core contributions. + +## What is Gerrit? + +Gerrit is a web-based code review tool that TYPO3 uses for managing patch submissions. Every code change must go through Gerrit review before being merged into TYPO3 Core. + +**Key Concepts**: +- **Patch/Change**: Single commit representing your contribution +- **Patchset**: Version of a patch (same Change-Id, updated code) +- **Review**: Process of evaluating code quality and correctness +- **Merge**: Final acceptance of patch into TYPO3 Core + +## Accessing Gerrit + +**URL**: https://review.typo3.org + +**Authentication**: Use TYPO3.org account credentials + +**Search Tool**: https://forger.typo3.com (easier searching) + +## Submitting Your First Patch + +### Prerequisites + +- Git configured for TYPO3 (see Environment Setup) +- SSH keys added to Gerrit +- Commit ready with proper message format +- All changes in single commit + +### Push to Gerrit + +```bash +# From your feature branch +git push origin HEAD:refs/for/main +``` + +**What happens**: +1. Git pushes to special Gerrit ref: `refs/for/main` +2. Gerrit creates new review +3. You receive SUCCESS message with review URL + +**Expected Output**: +``` +remote: Processing changes: new: 1, done +remote: +remote: SUCCESS +remote: +remote: https://review.typo3.org/c/Packages/TYPO3.CMS/+/12345 [NEW] +remote: +To ssh://review.typo3.org:29418/Packages/TYPO3.CMS.git + * [new branch] HEAD -> refs/for/main +``` + +**Save the review URL!** You'll need it to monitor progress. + +### Alternative Push Methods + +If you've configured default push settings: + +```bash +# Simple push (if remote.origin.push configured) +git push +``` + +## Continuous Integration + +After submission, Gerrit automatically runs tests: + +1. **GitLab CI** triggers test pipeline +2. Tests run across multiple PHP versions, code style checks, static analysis (PHPStan), and unit/functional tests +3. Results appear on Gerrit review page +4. Usually completes in 10-20 minutes + +**Status Indicators**: +- ✅ Green checkmark: All tests passed +- ❌ Red X: Tests failed +- ⏳ Clock: Tests running + +### IMPORTANT: New Patches Start in "Work in Progress" State + +**By default, newly submitted patches are marked as WIP (Work in Progress)**. This means: + +1. ⚠️ **Not visible to reviewers** - Core team won't see your patch for review +2. ✅ **CI tests still run** - You get test feedback immediately +3. 🔍 **You must verify yourself first** - Check all CI jobs before requesting review +4. ✅ **You must manually mark as ready** - Change state to "Ready for Review" when done + +**Workflow for New Submissions**: + +```bash +# 1. Push your patch +git push origin HEAD:refs/for/main + +# 2. Note the review URL from output +# https://review.typo3.org/c/Packages/TYPO3.CMS/+/12345 [WIP] + +# 3. Wait for CI to complete (10-20 minutes) + +# 4. CHECK ALL FAILING JOBS (critical step!) +# - Open the review URL +# - Look for any CI failures (red X marks) +# - For each failure, find the GitLab job URL +# - Read the ACTUAL ERROR LOGS (don't guess!) +# - Fix ALL issues before marking ready + +# 5. Once all tests pass, mark as ready for review +# +# Option A: Remove WIP via command line (empty push) +git commit --amend --allow-empty --no-edit +git push origin HEAD:refs/for/main%ready + +# Option B: Remove WIP via web UI +# a. Open review URL: https://review.typo3.org/c/Packages/TYPO3.CMS/+/XXXXX +# b. Click "Start Review" button (top right area, near your avatar) +# +# Notes: +# - %ready flag removes WIP state (even with empty pushes) +# - %wip flag sets WIP state: git push origin HEAD:refs/for/main%wip +# - SSH 'gerrit review' command does NOT support WIP flags (use git push flags instead) +``` + +### Investigating CI Failures (CRITICAL!) + +**NEVER assume what failed - ALWAYS check the actual job logs!** + +#### Step 1: Find All Failing Jobs + +On your Gerrit review page: +1. Scroll to the CI results section +2. Look for red ❌ marks next to job names +3. Note ALL failing job names (there might be multiple!) + +Common failing jobs: +- `cgl pre-merge` - Code style violations (PHP CS Fixer) +- `phpstan php X.X pre-merge` - Static analysis errors +- `unit php X.X pre-merge` - Unit test failures +- `functional php X.X pre-merge` - Functional test failures + +#### Step 2: Access GitLab Job Logs + +For each failing job: +1. Click on the failing job name in Gerrit +2. You'll be redirected to GitLab CI (https://git.typo3.org/typo3/CI/cms/-/jobs/XXXXXX) +3. Click the job log or raw log to see the actual error + +**Example**: If job #4896429 failed: +- URL: `https://git.typo3.org/typo3/CI/cms/-/jobs/4896429` +- Raw log: `https://git.typo3.org/typo3/CI/cms/-/jobs/4896429/raw` + +#### Step 3: Read and Understand ACTUAL Errors + +**DO NOT GUESS!** Read the actual error messages: + +**Code Style (cgl) Example**: +``` +Fixed 1 of 1 files in ... seconds. + +Checked 1 of 1 files in ... seconds. + 1) typo3/sysext/indexed_search/Tests/Unit/IndexerTest.php (single_quote) + ---------- begin diff ---------- +- body: "This content should not appear" ++ body: 'This content should not appear' + ----------- end diff ----------- +``` +**Fix**: Change double quotes to single quotes in test file. + +**PHPStan Example**: +``` +------ ------------------------------------------------------------------------- + Line indexed_search/Tests/Unit/IndexerTest.php +------ ------------------------------------------------------------------------- + 236 Call to static method PHPUnit\Framework\Assert::assertNotNull() + with string will always evaluate to true. +------ ------------------------------------------------------------------------- +``` +**Fix**: Remove `assertNotNull()` call - it's redundant for string return types. + +**Unit Test Failure Example**: +``` +FAILURES! +Tests: 11683, Assertions: 20300, Failures: 1. + +There was 1 failure: + +1) TYPO3\CMS\IndexedSearch\Tests\Unit\IndexerTest::bodyDescriptionReturnsEmptyStringWhenMaxLengthIsZero +Failed asserting that two strings are equal. +--- Expected ++++ Actual +@@ @@ +-'' ++'This content should not appear in description' +``` +**Fix**: Test logic is wrong - review the test expectations. + +#### Step 4: Fix ALL Issues + +⚠️ **CRITICAL**: A CI pipeline may have multiple failing jobs. Fix ALL of them: + +```bash +# Example: 5 jobs failed (cgl, phpstan, 3x unit tests) +# You must fix: +# 1. Code style issues (single quotes) +# 2. PHPStan warnings (remove redundant assertions) +# 3. Unit test failures (fix test logic) + +# Make all fixes +vim typo3/sysext/indexed_search/Tests/Unit/IndexerTest.php + +# Stage changes +git add typo3/sysext/indexed_search/Tests/Unit/IndexerTest.php + +# Amend commit +git commit --amend --no-edit + +# Push updated patchset +git push origin HEAD:refs/for/main +``` + +#### Step 5: Wait for Re-verification + +After pushing fixes: +1. CI automatically runs again +2. Old failed votes (Verified-1) are removed +3. Wait for all jobs to complete +4. Verify ALL jobs are now passing (green ✅) + +#### Step 6: Mark as Ready for Review + +Once ALL CI jobs pass: +1. Open your review on Gerrit +2. Click **"More"** → **"Start Review"** +3. Optionally add a comment: "Ready for review. All CI checks passing." +4. Your patch is now visible to core team reviewers + +### Common CI Failure Patterns + +| Job Type | Common Issues | Where to Look | +|----------|---------------|---------------| +| cgl (Code Style) | Double quotes, spacing, indentation | PHP CS Fixer diff in log | +| phpstan | Type errors, redundant code, undefined vars | Line numbers + error descriptions | +| unit tests | Test failures, assertion mismatches | Test name + expected vs actual | +| functional tests | Database issues, integration problems | Full stack trace in log | + +**If tests fail**: +1. ⚠️ **DO NOT GUESS** - Always read actual job logs +2. Check ALL failing jobs, not just the first one +3. Access GitLab CI job logs via links on Gerrit +4. Fix all issues in one patchset +5. Push updated patchset (next section) +6. Wait for re-verification +7. Mark as ready only when ALL jobs pass + +## Updating Your Patch + +When reviewers request changes or tests fail: + +### Step 1: Make Changes Locally + +```bash +# Make code changes +vim path/to/file.php + +# Stage changes +git add path/to/file.php +``` + +### Step 2: Amend Commit + +```bash +# Amend existing commit (DO NOT create new commit!) +git commit --amend + +# CRITICAL: Keep the Change-Id line unchanged! +``` + +### Step 3: Push Updated Patchset + +```bash +# Push to same Gerrit change +git push origin HEAD:refs/for/main +``` + +**What happens**: +- Gerrit matches Change-Id +- Creates new patchset (Patch Set 2, 3, etc.) +- Previous patchsets remain for comparison +- CI tests run again + +**Patchset Versioning**: +- Patch Set 1: Initial submission +- Patch Set 2: First update +- Patch Set 3: Second update +- etc. + +## Rebasing Your Patch + +### Why Rebase? + +While you're working, other contributors' patches get merged. Your patch becomes based on outdated code. Rebasing updates your patch to build on the latest codebase. + +### When to Rebase + +- Merge conflict indicator appears on Gerrit +- Regularly during development (best practice) +- Before running tests +- When requested by reviewers + +### Method 1: Browser-Based Rebase (Easiest) + +**Requirements**: No merge conflicts + +**Steps**: +1. Open your patch on Gerrit +2. Click **Rebase** button (top right) +3. Select "Rebase on top of the main branch" +4. Click **Rebase** + +Gerrit automatically: +- Rebases your change +- Creates new patchset +- Runs CI tests + +### Method 2: Command-Line Rebase + +**When to use**: Merge conflicts exist, or prefer manual control + +**Steps**: + +```bash +# Ensure on your feature branch +git checkout feature/105737-fix-indexed-search + +# Fetch latest changes +git fetch origin + +# Rebase onto main +git rebase origin/main +``` + +**If no conflicts**: +```bash +# Push rebased patch +git push origin HEAD:refs/for/main +``` + +**If conflicts occur**: See Resolving Merge Conflicts section below. + +### Alternative Rebase Methods + +**Option A: Pull with Rebase** +```bash +git pull --rebase origin main +``` + +**Option B: Interactive Rebase** (advanced) +```bash +git rebase -i origin/main +``` + +## Resolving Merge Conflicts + +### What Are Conflicts? + +Conflicts occur when: +- You modified file X +- Someone else modified same lines in file X +- Their patch merged first +- Git can't auto-merge + +### Conflict Resolution Process + +#### Step 1: Start Rebase + +```bash +git rebase origin/main +``` + +**Output with conflicts**: +``` +CONFLICT (content): Merge conflict in path/to/file.php +error: could not apply abc123... Your commit message +hint: Resolve all conflicts manually, mark them as resolved with +hint: "git add/rm ", then run "git rebase --continue". +``` + +#### Step 2: Identify Conflicted Files + +```bash +git status +``` + +**Output**: +``` +On branch feature/105737-fix-indexed-search +You are currently rebasing branch 'feature/105737-fix-indexed-search' on 'abc123'. + (fix conflicts and then run "git rebase --continue") + +Unmerged paths: + (use "git add ..." to mark resolution) + both modified: path/to/file.php +``` + +#### Step 3: Resolve Conflicts + +Open conflicted file in editor: + +```php +<<<<<<< HEAD +// Code from main branch (their changes) +$result = newFunction($data); +======= +// Your changes +$result = oldFunction($data); +>>>>>>> Your commit message +``` + +**Choose resolution**: + +**Option A: Keep their changes** +```php +$result = newFunction($data); +``` + +**Option B: Keep your changes** +```php +$result = oldFunction($data); +``` + +**Option C: Merge both** (most common) +```php +// Updated to use new function while preserving your logic +$result = newFunction($processedData); +``` + +Remove conflict markers (`<<<<<<<`, `=======`, `>>>>>>>`). + +#### Step 4: Mark as Resolved + +```bash +# Stage resolved files +git add path/to/file.php + +# Check all conflicts resolved +git status +``` + +#### Step 5: Continue Rebase + +```bash +git rebase --continue +``` + +If more conflicts exist, repeat steps 3-5. + +#### Step 6: Push Rebased Patch + +```bash +git push origin HEAD:refs/for/main +``` + +### Conflict Resolution Tips + +**Understand Context**: +- Review their changes: `git show HEAD:path/to/file.php` +- Review your changes: `git show feature/105737-fix-indexed-search:path/to/file.php` +- Check file history: `git log -- path/to/file.php` + +**Test After Resolution**: +```bash +# Run tests locally +composer test:unit +composer test:functional + +# Check syntax +php -l path/to/file.php +``` + +**Ask for Help**: +- Post in #typo3-cms-coredev Slack +- Comment on Gerrit review +- Reference conflicting patch if known + +### Aborting Rebase + +If rebase goes wrong: + +```bash +git rebase --abort +``` + +Returns to pre-rebase state. You can try again. + +## Review Process + +### Voting System + +**Code Review** (CR): +- **+2**: Looks good, approved +- **+1**: Looks mostly good +- **0**: Neutral (default) +- **-1**: Needs improvement +- **-2**: Do not merge (veto) + +**Verified** (V): +- **+1**: Tests passed +- **0**: Not yet tested +- **-1**: Tests failed + +**Merge Requirements**: +- At least **+2 Code Review** from core team member +- At least **+1 Verified** (CI tests passed) +- No unresolved **-2** votes +- At least 2 reviewers involved (one must be core team) + +### Typical Review Timeline + +**Simple Bugfixes**: 1-3 days +**Medium Features**: 3-7 days +**Complex Features**: 1-2 weeks +**Breaking Changes**: 2-4 weeks (more scrutiny) + +**Factors affecting timeline**: +- Code quality and completeness +- Test coverage +- Documentation +- Reviewer availability (volunteers!) +- Complexity and impact + +### Responding to Review Comments + +#### Step 1: Read Feedback Carefully + +- Understand what's being requested +- Ask questions if unclear +- Check if feedback applies to multiple locations + +#### Step 2: Implement Changes + +```bash +# Make requested changes +vim path/to/file.php + +# Stage and amend +git add path/to/file.php +git commit --amend + +# Push update +git push origin HEAD:refs/for/main +``` + +#### Step 3: Respond on Gerrit + +- Click **Reply** button +- Address each comment: + - "Done" - Simple confirmation + - "Fixed in PS3" - Reference patchset number + - Explain your approach if different from suggestion +- Thank reviewers +- Click **Send** + +#### Example Response + +``` +Thanks for the review! + +> Line 45: Consider using dependency injection + +Good point! I've refactored to use DI in PS3. + +> Line 120: Add type hint + +Added in PS3. Also added return type hints throughout. + +> Missing tests for edge case + +Added test case for empty string input in Tests/Unit/IndexerTest.php +``` + +### Getting More Reviews + +**If no reviews after 3-4 days**: + +1. **Advertise on Slack** (#typo3-cms-coredev): + ``` + I've submitted a patch for #105737 (indexed search crash). + Would appreciate reviews when you have time: https://review.typo3.org/c/Packages/TYPO3.CMS/+/12345 + ``` + +2. **Check patch quality**: + - Tests passing? + - Documentation complete? + - Follows coding standards? + - Clear commit message? + +3. **Ask specific reviewers** (if appropriate): + - Maintainers of affected area + - Previous contributors to same files + - Don't spam or DM randomly! + +## Gerrit Interface Guide + +### Review Page Sections + +**Header**: +- Status (Active, Merged, Abandoned) +- Subject and description +- Owner and reviewers +- CI test results + +**Files**: +- List of changed files +- Click file to see diff +- Add inline comments + +**History**: +- Patchset versions +- Comments and votes +- CI results per patchset + +**Related Changes**: +- Depends on / Needed by +- Related topics +- Conflicts with + +### Useful Gerrit Features + +**Diff Views**: +- **Side-by-side**: Compare old/new code +- **Unified**: Traditional diff format +- **Between patchsets**: Compare PS1 vs PS2 + +**Search**: +- Find your changes: `owner:self status:open` +- Find by issue: `bug:105737` +- Find by topic: `topic:indexed-search` + +**Keyboard Shortcuts**: +- `?`: Show all shortcuts +- `u`: Go up to dashboard +- `a`: Expand all inline comments +- `c`: Compose review comment +- `n/p`: Next/previous file + +## Advanced Topics + +### Cherry-Picking Patches + +Apply someone else's patch locally: + +```bash +# From Gerrit download dropdown, copy cherry-pick command +git fetch origin refs/changes/45/12345/3 && git cherry-pick FETCH_HEAD +``` + +### Topics + +Group related changes: + +```bash +git push origin HEAD:refs/for/main%topic=indexed-search-improvements +``` + +### Work In Progress (WIP) + +Mark patch as work-in-progress: + +```bash +git push origin HEAD:refs/for/main%wip +``` + +Or on Gerrit web UI: **More** → **Mark as Work In Progress** + +**Use WIP when**: +- Patch incomplete, not ready for review +- Want CI test results before review +- Demonstrating proof of concept + +**Remove WIP**: **More** → **Start Review** + +### Private Changes + +Keep change private (visible only to you and explicit reviewers): + +```bash +git push origin HEAD:refs/for/main%private +``` + +### Draft Comments + +Save review comments without publishing: +1. Add comments on files +2. Click **Save** instead of **Send** +3. Edit later +4. Publish when ready + +## Troubleshooting + +### "Change-Id not found" + +**Problem**: Missing or modified Change-Id + +**Solution**: +```bash +# Ensure commit-msg hook installed +ls -la .git/hooks/commit-msg + +# If missing, install +composer gerrit:setup + +# Amend commit to generate Change-Id +git commit --amend --no-edit +``` + +### "Prohibited by Gerrit" + +**Problem**: Pushing to wrong branch or permissions issue + +**Solution**: +```bash +# Verify push URL +git config remote.origin.pushurl +# Should be: ssh://@review.typo3.org:29418/Packages/TYPO3.CMS.git + +# Push to refs/for/main, not main directly +git push origin HEAD:refs/for/main +``` + +### "No New Changes" + +**Problem**: Pushing identical commit + +**Solution**: +- Make actual code changes +- Or amend commit message +- Then push again + +### Multiple Commits on Branch + +**Problem**: Accidentally created multiple commits + +**Solution**: Squash into one commit +```bash +# Interactive rebase +git rebase -i origin/main + +# In editor, change all but first "pick" to "squash" +# Save and exit +# Edit combined commit message +# Push +``` + +## Best Practices + +1. **One commit per patch**: Squash multiple commits into one +2. **Rebase regularly**: Stay up-to-date with main branch +3. **Preserve Change-Id**: Never modify when amending +4. **Respond promptly**: Reply to reviews within 2-3 days +5. **Test locally first**: Run tests before pushing +6. **Clear communication**: Explain changes in Gerrit comments +7. **Be patient**: Reviewers are volunteers +8. **Learn from feedback**: Apply lessons to future patches + +## Resources + +- **Gerrit**: https://review.typo3.org +- **Forger Search**: https://forger.typo3.com +- **Gerrit Documentation**: https://review.typo3.org/Documentation/ +- **Slack**: #typo3-cms-coredev + +## Quick Command Reference + +| Action | Command | +|--------|---------| +| Push new patch | `git push origin HEAD:refs/for/main` | +| Update patch | `git commit --amend && git push origin HEAD:refs/for/main` | +| Rebase on main | `git fetch origin && git rebase origin/main` | +| Abort rebase | `git rebase --abort` | +| Continue rebase | `git rebase --continue` | +| Cherry-pick | `git fetch origin refs/changes/XX/XXXX/X && git cherry-pick FETCH_HEAD` | +| Push as WIP | `git push origin HEAD:refs/for/main%wip` | +| Test SSH | `ssh -p 29418 @review.typo3.org` | diff --git a/references/troubleshooting.md b/references/troubleshooting.md new file mode 100644 index 0000000..0019b87 --- /dev/null +++ b/references/troubleshooting.md @@ -0,0 +1,1025 @@ +# TYPO3 Contribution Troubleshooting Guide + +Common issues and solutions for TYPO3 Core contributions. + +## Git Configuration Issues + +### Problem: "Permission denied (publickey)" + +**Symptoms**: +``` +git@github.com: Permission denied (publickey). +fatal: Could not read from remote repository. +``` + +**Causes**: +- SSH keys not configured +- Wrong SSH key being used +- Key not added to Gerrit/GitHub + +**Solutions**: + +**Check SSH keys exist**: +```bash +ls -la ~/.ssh/ +# Look for id_ed25519 or id_rsa files +``` + +**Generate new SSH key if needed**: +```bash +ssh-keygen -t ed25519 -C "your-email@example.org" +``` + +**Add key to SSH agent**: +```bash +eval "$(ssh-agent -s)" +ssh-add ~/.ssh/id_ed25519 +``` + +**Test connection**: +```bash +# Test GitHub +ssh -T git@github.com + +# Test Gerrit +ssh -p 29418 @review.typo3.org +``` + +**Verify key on Gerrit**: +1. Visit https://review.typo3.org +2. Settings → SSH Keys +3. Ensure your public key is listed + +### Problem: "fatal: refusing to merge unrelated histories" + +**Symptoms**: +``` +fatal: refusing to merge unrelated histories +``` + +**Cause**: Trying to merge branches with no common ancestor + +**Solution**: +```bash +# Only if you're absolutely sure you want to merge +git pull origin main --allow-unrelated-histories + +# Better: Start fresh clone +cd .. +git clone git@github.com:typo3/typo3.git typo3-new +``` + +### Problem: "email address is not registered in your account" + +**Symptoms**: +``` +remote: ERROR: commit abc123: email address user@example.com is not registered +in your account, and you lack 'forge committer' permission. +remote: The following addresses are currently registered: +remote: other@example.com +``` + +**Cause**: Git commit email doesn't match any email registered in your Gerrit account + +**Solution**: + +**1. Check your Gerrit registered emails**: +Visit: https://review.typo3.org/settings#EmailAddresses + +**2. Update Git configuration to match**: +```bash +# Use one of your registered emails +git config user.email "your-registered@email.com" + +# If working in TYPO3 repo, update local config +cd /path/to/typo3 +git config user.email "your-registered@email.com" +``` + +**3. Amend the commit with new email**: +```bash +git commit --amend --reset-author --no-edit +``` + +**4. Push again**: +```bash +git push origin HEAD:refs/for/main +``` + +**Prevention**: Always verify your Git email matches Gerrit **before** making commits. Run `verify-prerequisites.sh` script before starting work. + +### Problem: "Your branch is ahead of 'origin/main' by X commits" + +**Symptoms**: +``` +Your branch is ahead of 'origin/main' by 5 commits. + (use "git push" to publish your local commits) +``` + +**Cause**: You have commits not yet pushed + +**Solutions**: + +**If commits should be separate patches**: +```bash +# Push each commit separately +git push origin :refs/for/main +``` + +**If commits should be one patch** (most common): +```bash +# Squash into single commit +git rebase -i origin/main +# Change all but first "pick" to "squash" +# Edit commit message +git push origin HEAD:refs/for/main +``` + +### Problem: "Branch 'main' set up to track remote branch 'main' from 'origin'" + +**Symptoms**: Can't push, tracking wrong remote + +**Solution**: +```bash +# Reset remote configuration +git config remote.origin.pushurl ssh://@review.typo3.org:29418/Packages/TYPO3.CMS.git +git config remote.origin.push +refs/heads/main:refs/for/main +``` + +## Gerrit Issues + +### Problem: "Change-Id not found in commit message footer" + +**Symptoms**: +``` +remote: ERROR: commit abc123: missing Change-Id in message footer +``` + +**Cause**: commit-msg hook not installed or bypassed + +**Solutions**: + +**Install hook**: +```bash +composer gerrit:setup + +# Or manually +cp Build/git-hooks/commit-msg .git/hooks/ +chmod +x .git/hooks/commit-msg +``` + +**Fix existing commit**: +```bash +# Amend to trigger hook +git commit --amend --no-edit + +# Verify Change-Id added +git log -1 +``` + +**If Change-Id still missing**: +```bash +# Manually run hook +.git/hooks/commit-msg .git/COMMIT_EDITMSG + +# Amend with new message +git commit --amend -F .git/COMMIT_EDITMSG +``` + +### Problem: "Prohibited by Gerrit: not permitted to upload" + +**Symptoms**: +``` +remote: ERROR: [a1b2c3] missing Change-Id in message footer +remote: ERROR: Prohibited by Gerrit: not permitted to upload +``` + +**Causes**: +- Pushing to wrong ref +- Account permissions issue +- SSH key not configured + +**Solutions**: + +**Check push URL**: +```bash +git config remote.origin.pushurl +# Should be: ssh://@review.typo3.org:29418/Packages/TYPO3.CMS.git +``` + +**Push to correct ref**: +```bash +# Push to refs/for/main, NOT directly to main +git push origin HEAD:refs/for/main +``` + +**Verify SSH connection**: +```bash +ssh -p 29418 @review.typo3.org +``` + +**Check username**: +```bash +git config remote.origin.pushurl +# Ensure matches your Gerrit username +``` + +### Problem: "Invalid Change-Id" + +**Symptoms**: Gerrit rejects Change-Id format + +**Cause**: Manually created or corrupted Change-Id + +**Solution**: +```bash +# Remove invalid Change-Id from commit message +git commit --amend +# Delete the Change-Id line +# Save and exit + +# Re-amend to generate new Change-Id +git commit --amend --no-edit + +# Verify format: "Change-Id: I" followed by 40 hex characters +git log -1 | grep Change-Id +``` + +### Problem: "New Patchset Not Appearing" + +**Symptoms**: Push succeeds but no new patchset on Gerrit + +**Causes**: +- No actual changes (identical commit) +- Change-Id modified (created new review instead) + +**Solutions**: + +**Check if new review created**: +- Look for different review URL in push output +- Search Gerrit for your recent changes + +**Ensure actual changes**: +```bash +# View last commit changes +git show HEAD + +# Compare with Gerrit patchset +git fetch origin refs/changes/XX/XXXX/X +git diff FETCH_HEAD +``` + +**If Change-Id was modified**: +```bash +# Get original Change-Id from Gerrit +# Edit commit message to restore it +git commit --amend +# Restore original Change-Id +# Save and push +``` + +## Rebase and Merge Issues + +### Problem: "CONFLICT (content): Merge conflict in file.php" + +**Symptoms**: +``` +CONFLICT (content): Merge conflict in path/to/file.php +Automatic merge failed; fix conflicts and then commit the result. +``` + +**Solution**: See "Resolving Merge Conflicts" in gerrit-workflow.md + +**Quick steps**: +```bash +# 1. Open conflicted file, resolve conflicts +vim path/to/file.php + +# 2. Remove conflict markers (<<<<<<<, =======, >>>>>>>) + +# 3. Stage resolved file +git add path/to/file.php + +# 4. Continue rebase +git rebase --continue + +# 5. Push updated patch +git push origin HEAD:refs/for/main +``` + +### Problem: "Cannot rebase: You have unstaged changes" + +**Symptoms**: +``` +error: cannot rebase: You have unstaged changes. +error: Please commit or stash them. +``` + +**Solutions**: + +**Option A: Stash changes**: +```bash +git stash +git rebase origin/main +git stash pop +``` + +**Option B: Commit changes**: +```bash +git add . +git commit --amend +git rebase origin/main +``` + +**Option C: Discard changes** (if unwanted): +```bash +git checkout -- . +git rebase origin/main +``` + +### Problem: "Already up to date" + +**Symptoms**: Rebase says "up to date" but Gerrit shows conflicts + +**Cause**: Rebasing wrong branch or remote not updated + +**Solutions**: +```bash +# Fetch latest changes first +git fetch origin + +# Ensure on correct branch +git branch +# Should show * feature/your-branch + +# Try rebase again +git rebase origin/main +``` + +## Test Failures + +### Problem: "Bamboo CI Tests Failing" + +**Symptoms**: Red X on Gerrit review, tests failed + +**Solutions**: + +**View test results**: +1. Click test result on Gerrit +2. Read error messages +3. Identify failing tests + +**Run tests locally**: +```bash +# Unit tests +composer test:unit + +# Specific test class +composer test:unit -- path/to/TestClass.php + +# Functional tests +composer test:functional + +# All tests +composer test +``` + +**Common test failures**: + +**PHP syntax error**: +```bash +php -l path/to/file.php +``` + +**Coding standards**: +```bash +composer cs:check +composer cs:fix +``` + +**Missing dependencies**: +```bash +composer install +``` + +**Fix and resubmit**: +```bash +# After fixing +git add . +git commit --amend +git push origin HEAD:refs/for/main +``` + +### Problem: "Tests Pass Locally But Fail on CI" + +**Causes**: +- PHP version differences +- Missing dependencies +- Environment-specific issues + +**Solutions**: + +**Check PHP version**: +```bash +# Local version +php -v + +# CI uses multiple versions (7.4, 8.0, 8.1, 8.2) +# Ensure code compatible with all +``` + +**Test multiple PHP versions locally**: +```bash +# Using Docker +docker run --rm -v $(pwd):/app php:8.2-cli composer test + +docker run --rm -v $(pwd):/app php:8.1-cli composer test +``` + +**Check CI logs carefully**: +- Look for deprecation warnings +- Check for missing extensions +- Verify database-specific issues + +## Development Environment Issues + +### Problem: "Composer command not found" + +**Solution**: +```bash +# Install Composer globally +curl -sS https://getcomposer.org/installer | php +sudo mv composer.phar /usr/local/bin/composer + +# Or use specific version +php composer.phar +``` + +### Problem: "DDEV not starting" + +**Solutions**: + +**Check Docker running**: +```bash +docker ps +``` + +**Restart DDEV**: +```bash +ddev restart +``` + +**Reset DDEV**: +```bash +ddev stop +ddev clean +ddev start +``` + +**Check logs**: +```bash +ddev logs +``` + +### Problem: "Out of memory" during Composer operations + +**Solution**: +```bash +# Increase PHP memory limit +php -d memory_limit=2G /usr/local/bin/composer install + +# Or set in php.ini +memory_limit = 2G +``` + +## Commit Message Issues + +### Problem: "Subject line too long" + +**Symptoms**: Validation fails, >72 characters + +**Solution**: +```bash +# Amend commit +git commit --amend + +# Shorten subject line to ≤52 chars (recommended) +# Or ≤72 chars (absolute max) +``` + +### Problem: "Wrong commit type" + +**Example**: Used `[FEATURE]` on bugfix + +**Solution**: +```bash +# Amend commit +git commit --amend + +# Change [FEATURE] to [BUGFIX] +# Save and exit +``` + +### Problem: "Missing footer tags" + +**Symptoms**: No Resolves or Releases tags + +**Solution**: +```bash +# Amend commit +git commit --amend + +# Add required footer: +# Resolves: #12345 +# Releases: main, 13.4 +# (Keep Change-Id unchanged!) +``` + +## Account Issues + +### Problem: "Can't access Gerrit" + +**Solutions**: + +**Verify TYPO3.org account**: +- Visit https://my.typo3.org +- Confirm account active + +**Sign in to Gerrit**: +- Visit https://review.typo3.org +- Click "Sign In" +- Use TYPO3.org credentials + +**Clear browser cache**: +- Cookies might be stale +- Try incognito/private mode + +### Problem: "SSH timeout connecting to Gerrit" + +**Symptoms**: +``` +ssh: connect to host review.typo3.org port 29418: Operation timed out +``` + +**Causes**: +- Firewall blocking port 29418 +- Network restrictions +- Corporate VPN issues + +**Solutions**: + +**Try different network**: +- Use mobile hotspot +- Try from different location + +**Check firewall**: +```bash +telnet review.typo3.org 29418 +``` + +**Use HTTPS instead** (less common for TYPO3): +```bash +git config remote.origin.url https://review.typo3.org/Packages/TYPO3.CMS +``` + +## Getting Help + +### Where to Ask + +**Slack**: #typo3-cms-coredev +``` +@here I'm having trouble with [issue]. I've tried [solutions]. +Error message: [paste error] +Gerrit review: https://review.typo3.org/c/... +``` + +**Forge**: https://forge.typo3.org +- Create issue if you found a bug in contribution process + +**Documentation**: https://docs.typo3.org/m/typo3/guide-contributionworkflow/ + +### What to Include When Asking + +1. **What you're trying to do** +2. **What you've tried** +3. **Error messages** (full text) +4. **Links** (Gerrit review, Forge issue) +5. **Environment** (OS, PHP version, Git version) +6. **Relevant commands** and their output + +### Example Help Request + +``` +I'm trying to push my patch for #105737 but getting this error: + +``` +remote: ERROR: missing Change-Id in message footer +``` + +I've tried: +- Running composer gerrit:setup +- Checking that .git/hooks/commit-msg exists and is executable +- Running git commit --amend --no-edit + +My setup: +- macOS 12.6 +- Git 2.37.1 +- PHP 8.1.12 + +Review (if already created): https://review.typo3.org/c/Packages/TYPO3.CMS/+/12345 + +Any ideas what I'm missing? +``` + +## Preventive Measures + +### Before Starting + +- [ ] Run `scripts/verify-prerequisites.sh` +- [ ] Verify SSH access to Gerrit +- [ ] Check git configuration +- [ ] Ensure hooks installed + +### Before Committing + +- [ ] Run tests locally +- [ ] Check coding standards +- [ ] Validate commit message format +- [ ] Review changes with `git diff` + +### Before Pushing + +- [ ] Rebase on latest main +- [ ] Ensure single commit +- [ ] Verify Change-Id present +- [ ] Test one more time + +### After Pushing + +- [ ] Verify patch on Gerrit +- [ ] Watch CI test results +- [ ] Respond to initial feedback +- [ ] Update if tests fail + +## CI/GitLab Issues + +### Problem: "How do I find ALL failing CI jobs?" + +**Critical**: Never assume what failed - always check ALL job logs! + +**Step-by-Step Process**: + +**1. Open your Gerrit review**: +``` +https://review.typo3.org/c/Packages/TYPO3.CMS/+/YOUR_NUMBER +``` + +**2. Find CI Results section**: +- Scroll down to see GitLab CI results +- Look for red ❌ marks next to job names +- Note ALL failing job names (there may be multiple!) + +**3. For each failing job**: +- Click the job name/link +- You'll be redirected to GitLab: `https://git.typo3.org/typo3/CI/cms/-/jobs/XXXXXX` +- Click "Show complete raw" or append `/raw` to URL +- Read the ACTUAL error messages + +**Common Failing Jobs**: +- `cgl pre-merge` - Code style violations +- `phpstan php X.X pre-merge` - Static analysis errors +- `unit php X.X pre-merge` - Unit test failures (may fail on multiple PHP versions) +- `functional php X.X pre-merge` - Functional test failures + +### Problem: "Code Style (cgl) Failed" + +**Symptoms**: +``` +1) path/to/File.php (single_quote) + ---------- begin diff ---------- +- body: "some string" ++ body: 'some string' + ----------- end diff ----------- +``` + +**Cause**: Code doesn't match TYPO3 coding standards (PSR-12 + TYPO3 rules) + +**Common Issues**: +- Double quotes instead of single quotes for simple strings +- Wrong indentation (spaces vs tabs) +- Missing/extra spaces +- Line length violations + +**Solutions**: + +**Option 1: Auto-fix with PHP CS Fixer** (recommended): +```bash +# Install PHP CS Fixer if not available +composer require --dev friendsofphp/php-cs-fixer + +# Run fixer on specific file +./Build/Scripts/cglFixMyCommit.sh + +# Or manually on specific files +vendor/bin/php-cs-fixer fix path/to/File.php +``` + +**Option 2: Manual fix**: +```bash +# Read the diff carefully +# Fix issues manually in your editor +vim path/to/File.php + +# Amend and push +git add path/to/File.php +git commit --amend --no-edit +git push origin HEAD:refs/for/main +``` + +### Problem: "PHPStan Failed" + +**Symptoms**: +``` +------ --------------------------------------------------------------------- + Line path/to/File.php +------ --------------------------------------------------------------------- + 236 Call to static method Assert::assertNotNull() + with string will always evaluate to true. +------ --------------------------------------------------------------------- +``` + +**Cause**: Static analysis detected potential bugs or redundant code + +**Common Issues**: +- Redundant type checks (asserting non-null on typed return values) +- Undefined variables +- Type mismatches +- Incorrect PHPDoc annotations + +**Solutions**: + +```bash +# Run PHPStan locally to see all issues +./Build/Scripts/runTests.sh -s phpstan + +# Fix the issues: +# - Remove redundant assertions +# - Add proper type hints +# - Fix type mismatches +# - Update PHPDoc blocks + +# Example: Remove redundant assertNotNull() +# Before: +$result = $subject->bodyDescription($dto); // returns string +self::assertNotNull($result); // WRONG - string can't be null + +# After: +$result = $subject->bodyDescription($dto); +self::assertNotEmpty($result); // CORRECT - checks string is not empty + +# Amend and push +git add path/to/File.php +git commit --amend --no-edit +git push origin HEAD:refs/for/main +``` + +### Problem: "Unit Tests Failed" + +**Symptoms**: +``` +FAILURES! +Tests: 11683, Assertions: 20300, Failures: 1. + +1) Vendor\Package\Tests\Unit\ClassTest::testMethod +Failed asserting that two strings are equal. +--- Expected ++++ Actual +@@ @@ +-'' ++'unexpected content' +``` + +**Cause**: Test assertions don't match actual behavior + +**Solutions**: + +**1. Read the full error**: +```bash +# Get the full test output from GitLab job log +# Look for: +# - Which test failed (full class name and method) +# - What was expected vs actual +# - Any exception messages or stack traces +``` + +**2. Run test locally**: +```bash +# Run specific test +./Build/Scripts/runTests.sh -s unit path/to/Tests/Unit/ClassTest.php::testMethod + +# Or run all tests in file +./Build/Scripts/runTests.sh -s unit path/to/Tests/Unit/ClassTest.php +``` + +**3. Fix the issue**: +- If test logic is wrong: Update test assertions +- If implementation is wrong: Fix the implementation +- If test is no longer valid: Remove it (with good reason!) + +**4. Verify and push**: +```bash +# Run tests locally to confirm fix +./Build/Scripts/runTests.sh -s unit + +# Amend and push +git add . +git commit --amend --no-edit +git push origin HEAD:refs/for/main +``` + +### Problem: "Multiple jobs failed - which do I fix first?" + +**Answer**: Fix ALL of them in ONE patchset! + +**Process**: + +```bash +# 1. List all failures +# Example: cgl, phpstan, 3x unit tests all failed + +# 2. Read ALL job logs +# - cgl: Double quotes issue +# - phpstan: Redundant assertion +# - unit tests: Test logic error + +# 3. Fix all issues locally +vim Tests/Unit/IndexerTest.php +# - Change double quotes to single quotes (cgl fix) +# - Remove assertNotNull() (phpstan fix) +# - Fix test logic (unit test fix) + +# 4. Verify fixes locally +./Build/Scripts/cglFixMyCommit.sh +./Build/Scripts/runTests.sh -s phpstan +./Build/Scripts/runTests.sh -s unit + +# 5. Commit and push ONCE +git add Tests/Unit/IndexerTest.php +git commit --amend --no-edit +git push origin HEAD:refs/for/main + +# 6. Wait for re-verification +# All 5 jobs should now pass +``` + +### Problem: "Patch is in WIP state - reviewers can't see it" + +**Symptoms**: +- Patch shows [WIP] tag on Gerrit +- No review feedback after several days +- CI tests passed but no reviews + +**Cause**: New patches are WIP by default - reviewers can't see them! + +**Solution**: + +**1. Verify all CI jobs pass**: +``` +Go to Gerrit review page +Check all CI results are green ✅ +If any red ❌, fix those first! +``` + +**2. Mark as ready for review**: +``` +Click "More" button (top right on Gerrit) +Click "Start Review" +Optionally add comment: "Ready for review. All CI checks passing." +``` + +**3. Advertise on Slack** (optional, for visibility): +``` +#typo3-cms-coredev channel: +"Submitted patch for #105737 - ready for review when you have time: +https://review.typo3.org/c/Packages/TYPO3.CMS/+/12345" +``` + +### Problem: "CI takes forever to run" + +**Typical Duration**: 10-20 minutes for full pipeline + +**If longer than 30 minutes**: +- Check GitLab CI status page: https://git.typo3.org/typo3/CI/cms/-/pipelines +- Pipeline might be queued behind other patches +- Check Slack #typo3-cms-coredev for CI outages +- Be patient - pipelines run in order + +**Don't**: +- Push multiple updates while CI is running +- Spam push repeatedly +- Rebase while CI is active + +**Do**: +- Wait for current CI to finish +- Make all fixes in one commit +- Push once with all fixes + +## Quick Diagnostic Commands + +```bash +# Check git configuration +git config -l | grep -E "user\.|remote\.origin" + +# Verify SSH connection +ssh -T -p 29418 @review.typo3.org + +# Check git hooks +ls -la .git/hooks/ | grep -E "commit-msg|pre-commit" + +# View last commit +git log -1 --pretty=full + +# Check remote configuration +git remote -v + +# Verify Change-Id in last commit +git log -1 | grep Change-Id + +# Check for unstaged changes +git status + +# View diff of changes +git diff HEAD + +# List all branches +git branch -a +``` + +## Additional Resources + +- **Contribution Guide**: https://docs.typo3.org/m/typo3/guide-contributionworkflow/ +- **Gerrit Documentation**: https://review.typo3.org/Documentation/ +- **Git Documentation**: https://git-scm.com/doc +- **Slack**: https://typo3.slack.com (#typo3-cms-coredev) +- **Forge**: https://forge.typo3.org + + +--- + +## Gerrit WIP State Management + +### Problem: "How do I mark my patch as ready for review?" + +**Background**: +- All new patches start as WIP (Work in Progress) automatically +- Reviewers cannot see WIP patches +- You must mark patches as "ready" before reviewers can see them + +**Solution A - Command Line (Recommended)**: + +Remove WIP state via git push with %ready flag: + +```bash +# If no code changes needed, create empty patchset +git commit --amend --allow-empty --no-edit +git push origin HEAD:refs/for/main%ready +``` + +**Solution B - Web UI**: + +1. Open your review: `https://review.typo3.org/c/Packages/TYPO3.CMS/+/XXXXX` +2. Click "Start Review" button (top right, near your avatar) +3. Done - patch now visible to reviewers + +**Solution C - Combined with Code Changes**: + +If you're pushing code fixes, add %ready to remove WIP at the same time: + +```bash +git commit --amend +git push origin HEAD:refs/for/main%ready +``` + +**Setting WIP State**: + +```bash +# Mark as WIP on initial push +git push origin HEAD:refs/for/main%wip + +# Or set WIP via web UI: More menu → "Mark as Work in Progress" +``` + +**What DOESN'T Work**: + +```bash +# ❌ SSH 'gerrit review' command has NO WIP flags +ssh -p 29418 user@review.typo3.org gerrit review --ready 12345,1 +ssh -p 29418 user@review.typo3.org gerrit review --wip 12345,1 +``` + +**Key Points**: + +- ✅ Use `%wip` and `%ready` flags with `git push` +- ✅ Empty pushes with `--allow-empty` are accepted +- ❌ SSH `gerrit review` command does NOT support WIP operations +- ✅ Web UI works but command line is faster + diff --git a/scripts/create-commit-message.py b/scripts/create-commit-message.py new file mode 100755 index 0000000..4532b90 --- /dev/null +++ b/scripts/create-commit-message.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python3 +""" +TYPO3 Core Contribution Commit Message Generator +Creates properly formatted commit messages following TYPO3 standards +""" + +import argparse +import sys +import re +from typing import Optional + + +COMMIT_TYPES = { + 'BUGFIX': 'Bug fixes', + 'FEATURE': 'New features (main branch only)', + 'TASK': 'Refactoring, cleanup, miscellaneous', + 'DOCS': 'Documentation changes', + 'SECURITY': 'Security vulnerability fixes' +} + +BREAKING_CHANGE_PREFIX = '[!!!]' + + +def validate_subject(subject: str, has_breaking: bool) -> tuple[bool, Optional[str]]: + """Validate subject line against TYPO3 rules""" + max_length = 52 if not has_breaking else 47 # Account for [!!!] prefix + + if len(subject) > 72: + return False, "Subject line exceeds 72 characters (absolute limit)" + + if len(subject) > max_length: + return False, f"Subject line exceeds {max_length} characters (recommended limit)" + + if not subject[0].isupper(): + return False, "Subject must start with uppercase letter" + + if subject.endswith('.'): + return False, "Subject should not end with a period" + + # Check for imperative mood (simple heuristic) + past_tense_endings = ['ed', 'ing'] + first_word = subject.split()[0].lower() + if any(first_word.endswith(end) for end in past_tense_endings): + return False, f"Use imperative mood ('{first_word}' appears to be past/present continuous tense)" + + return True, None + + +def wrap_text(text: str, width: int = 72) -> str: + """Wrap text at specified width""" + words = text.split() + lines = [] + current_line = [] + current_length = 0 + + for word in words: + word_length = len(word) + if current_length + word_length + len(current_line) > width: + if current_line: + lines.append(' '.join(current_line)) + current_line = [word] + current_length = word_length + else: + current_line.append(word) + current_length += word_length + + if current_line: + lines.append(' '.join(current_line)) + + return '\n'.join(lines) + + +def parse_releases(releases_str: str) -> list[str]: + """Parse comma-separated release versions""" + releases = [r.strip() for r in releases_str.split(',')] + # Validate format + valid_releases = [] + for release in releases: + if release == 'main' or re.match(r'^\d+\.\d+$', release): + valid_releases.append(release) + else: + print(f"Warning: Invalid release format '{release}', skipping") + return valid_releases + + +def main(): + parser = argparse.ArgumentParser( + description='Generate TYPO3-compliant commit messages', + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=''' +Examples: + %(prog)s --issue 105737 --type BUGFIX + %(prog)s --issue 105737 --type FEATURE --breaking + %(prog)s --type TASK --related 12345,12346 + ''' + ) + + parser.add_argument('--issue', type=int, help='Forge issue number') + parser.add_argument('--related', help='Related issue numbers (comma-separated)') + parser.add_argument('--type', choices=COMMIT_TYPES.keys(), required=True, + help='Commit type') + parser.add_argument('--breaking', action='store_true', + help='Mark as breaking change (adds [!!!] prefix)') + parser.add_argument('--releases', default='main', + help='Target releases (comma-separated, e.g., "main, 13.4, 12.4")') + parser.add_argument('--output', help='Output file (default: print to stdout)') + + args = parser.parse_args() + + # Interactive mode + print("=== TYPO3 Commit Message Generator ===\n") + + # Get subject line + print(f"Commit Type: [{args.type}]") + if args.breaking: + print(f"Breaking Change: Yes (will add {BREAKING_CHANGE_PREFIX} prefix)") + print() + + subject = input("Enter subject line (max 52 chars, imperative mood): ").strip() + + # Validate subject + valid, error = validate_subject(subject, args.breaking) + if not valid: + print(f"\n❌ Error: {error}") + sys.exit(1) + + # Get description + print("\nEnter description (explain how and why, not what).") + print("Press Ctrl+D (Linux/Mac) or Ctrl+Z (Windows) when done:") + description_lines = [] + try: + while True: + line = input() + description_lines.append(line) + except EOFError: + pass + + description = '\n'.join(description_lines).strip() + if description: + description = wrap_text(description) + + # Build commit message + type_prefix = f"{BREAKING_CHANGE_PREFIX}{args.type}" if args.breaking else args.type + message = f"[{type_prefix}] {subject}\n\n" + + if description: + message += f"{description}\n\n" + + # Add footer + if args.issue: + message += f"Resolves: #{args.issue}\n" + + if args.related: + related_issues = [f"#{num.strip()}" for num in args.related.split(',')] + for issue in related_issues: + message += f"Related: {issue}\n" + + releases = parse_releases(args.releases) + if releases: + message += f"Releases: {', '.join(releases)}\n" + + # Output + print("\n" + "="*60) + print("Generated Commit Message:") + print("="*60) + print(message) + print("="*60) + print("\nNote: Change-Id will be added automatically by git hook") + print("="*60) + + if args.output: + with open(args.output, 'w') as f: + f.write(message) + print(f"\n✓ Commit message saved to: {args.output}") + print(f" Use: git commit -F {args.output}") + else: + print("\nTo use this message:") + print(" 1. Copy the message above") + print(" 2. Run: git commit") + print(" 3. Paste into your editor") + + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/scripts/create-forge-issue.sh b/scripts/create-forge-issue.sh new file mode 100755 index 0000000..58946d5 --- /dev/null +++ b/scripts/create-forge-issue.sh @@ -0,0 +1,192 @@ +#!/bin/bash +# Create TYPO3 Forge issue via Redmine REST API +# +# Usage: +# 1. Get your API key from https://forge.typo3.org/my/account +# 2. Set environment variable: export FORGE_API_KEY="your-key-here" +# 3. Run: ./scripts/create-forge-issue.sh + +set -e + +# Color output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Check for API key +if [ -z "$FORGE_API_KEY" ]; then + echo -e "${RED}Error: FORGE_API_KEY environment variable not set${NC}" + echo "" + echo "Get your API key from: https://forge.typo3.org/my/account" + echo "Then set it: export FORGE_API_KEY=\"your-key-here\"" + exit 1 +fi + +# Check for required tools +for tool in curl jq; do + if ! command -v $tool &> /dev/null; then + echo -e "${RED}Error: $tool is required but not installed${NC}" + exit 1 + fi +done + +echo -e "${GREEN}TYPO3 Forge Issue Creator${NC}" +echo "" + +# Interactive prompts +read -p "Issue subject (title): " SUBJECT +if [ -z "$SUBJECT" ]; then + echo -e "${RED}Error: Subject is required${NC}" + exit 1 +fi + +echo "" +echo "Issue description (multi-line, press Ctrl+D when done):" +DESCRIPTION=$(cat) +if [ -z "$DESCRIPTION" ]; then + echo -e "${RED}Error: Description is required${NC}" + exit 1 +fi + +echo "" +echo "Select tracker type:" +echo " 1) Bug" +echo " 2) Feature" +echo " 3) Task" +read -p "Choice [1]: " TRACKER_CHOICE +TRACKER_CHOICE=${TRACKER_CHOICE:-1} + +case $TRACKER_CHOICE in + 1) TRACKER_ID=1; TRACKER_NAME="Bug" ;; + 2) TRACKER_ID=2; TRACKER_NAME="Feature" ;; + 3) TRACKER_ID=4; TRACKER_NAME="Task" ;; + *) echo -e "${RED}Invalid choice${NC}"; exit 1 ;; +esac + +echo "" +echo "Select priority:" +echo " 1) Must have" +echo " 2) Should have (recommended)" +echo " 3) Could have" +read -p "Choice [2]: " PRIORITY_CHOICE +PRIORITY_CHOICE=${PRIORITY_CHOICE:-2} + +case $PRIORITY_CHOICE in + 1) PRIORITY_ID=3; PRIORITY_NAME="Must have" ;; + 2) PRIORITY_ID=4; PRIORITY_NAME="Should have" ;; + 3) PRIORITY_ID=5; PRIORITY_NAME="Could have" ;; + *) echo -e "${RED}Invalid choice${NC}"; exit 1 ;; +esac + +echo "" +read -p "TYPO3 version affected (e.g., 13, 14) [13]: " TYPO3_VERSION +TYPO3_VERSION=${TYPO3_VERSION:-13} + +echo "" +echo "Select category (common ones, or enter ID manually):" +echo " 1) Miscellaneous (975)" +echo " 2) Backend API (971)" +echo " 3) Backend User Interface (972)" +echo " 4) Frontend (977)" +echo " 5) Database API (974)" +echo " 6) Indexed Search (1000)" +echo " 7) Extension Manager (976)" +echo " 8) Documentation (1004)" +echo " 9) Enter category ID manually" +read -p "Choice [1]: " CATEGORY_CHOICE +CATEGORY_CHOICE=${CATEGORY_CHOICE:-1} + +case $CATEGORY_CHOICE in + 1) CATEGORY_ID=975; CATEGORY_NAME="Miscellaneous" ;; + 2) CATEGORY_ID=971; CATEGORY_NAME="Backend API" ;; + 3) CATEGORY_ID=972; CATEGORY_NAME="Backend User Interface" ;; + 4) CATEGORY_ID=977; CATEGORY_NAME="Frontend" ;; + 5) CATEGORY_ID=974; CATEGORY_NAME="Database API" ;; + 6) CATEGORY_ID=1000; CATEGORY_NAME="Indexed Search" ;; + 7) CATEGORY_ID=976; CATEGORY_NAME="Extension Manager" ;; + 8) CATEGORY_ID=1004; CATEGORY_NAME="Documentation" ;; + 9) + read -p "Enter category ID: " CATEGORY_ID + CATEGORY_NAME="Custom ($CATEGORY_ID)" + ;; + *) echo -e "${RED}Invalid choice${NC}"; exit 1 ;; +esac + +# Optional tags +echo "" +read -p "Tags (comma-separated, optional): " TAGS + +# Summary +echo "" +echo -e "${YELLOW}Summary:${NC}" +echo " Tracker: $TRACKER_NAME" +echo " Subject: $SUBJECT" +echo " Priority: $PRIORITY_NAME" +echo " Category: $CATEGORY_NAME" +echo " TYPO3 Version: $TYPO3_VERSION" +[ -n "$TAGS" ] && echo " Tags: $TAGS" +echo "" + +read -p "Create this issue? [Y/n]: " CONFIRM +CONFIRM=${CONFIRM:-Y} + +if [[ ! $CONFIRM =~ ^[Yy]$ ]]; then + echo "Cancelled." + exit 0 +fi + +# Build JSON payload +JSON_PAYLOAD=$(jq -n \ + --arg subject "$SUBJECT" \ + --arg description "$DESCRIPTION" \ + --argjson tracker "$TRACKER_ID" \ + --argjson category "$CATEGORY_ID" \ + --argjson priority "$PRIORITY_ID" \ + --arg typo3_version "$TYPO3_VERSION" \ + --arg tags "$TAGS" \ + '{ + issue: { + project_id: "typo3cms-core", + subject: $subject, + description: $description, + tracker_id: $tracker, + category_id: $category, + priority_id: $priority, + custom_fields: [ + {id: 4, value: $typo3_version} + ] + (if $tags != "" then [{id: 3, value: $tags}] else [] end) + } + }') + +# Create issue +echo "" +echo -e "${YELLOW}Creating issue...${NC}" + +RESPONSE=$(curl -s -X POST \ + -H "Content-Type: application/json" \ + -H "X-Redmine-API-Key: $FORGE_API_KEY" \ + -d "$JSON_PAYLOAD" \ + https://forge.typo3.org/issues.json) + +# Check for errors +if echo "$RESPONSE" | jq -e '.errors' > /dev/null 2>&1; then + echo -e "${RED}Error creating issue:${NC}" + echo "$RESPONSE" | jq -r '.errors[]' + exit 1 +fi + +# Extract issue details +ISSUE_ID=$(echo "$RESPONSE" | jq -r '.issue.id') +ISSUE_URL="https://forge.typo3.org/issues/${ISSUE_ID}" + +echo "" +echo -e "${GREEN}Success! Issue created:${NC}" +echo "" +echo " Issue #: $ISSUE_ID" +echo " URL: $ISSUE_URL" +echo "" +echo -e "${YELLOW}Next steps:${NC}" +echo " 1. Use in commit message: ${GREEN}Resolves: #${ISSUE_ID}${NC}" +echo " 2. Create feature branch: ${GREEN}git checkout -b feature/${ISSUE_ID}-description${NC}" +echo "" diff --git a/scripts/query-forge-metadata.sh b/scripts/query-forge-metadata.sh new file mode 100755 index 0000000..7a13b98 --- /dev/null +++ b/scripts/query-forge-metadata.sh @@ -0,0 +1,102 @@ +#!/bin/bash +# Query TYPO3 Forge project metadata via Redmine REST API +# +# Usage: +# 1. Get your API key from https://forge.typo3.org/my/account +# 2. Set environment variable: export FORGE_API_KEY="your-key-here" +# 3. Run: ./scripts/query-forge-metadata.sh [categories|trackers|all] + +set -e + +# Color output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Check for API key +if [ -z "$FORGE_API_KEY" ]; then + echo -e "${RED}Error: FORGE_API_KEY environment variable not set${NC}" + echo "" + echo "Get your API key from: https://forge.typo3.org/my/account" + echo "Then set it: export FORGE_API_KEY=\"your-key-here\"" + exit 1 +fi + +# Check for required tools +for tool in curl jq; do + if ! command -v $tool &> /dev/null; then + echo -e "${RED}Error: $tool is required but not installed${NC}" + exit 1 + fi +done + +# Parse arguments +QUERY_TYPE=${1:-all} + +# Fetch project metadata +echo -e "${YELLOW}Fetching TYPO3 Core project metadata...${NC}" +echo "" + +RESPONSE=$(curl -s \ + -H "X-Redmine-API-Key: $FORGE_API_KEY" \ + https://forge.typo3.org/projects/typo3cms-core.json) + +# Check for errors +if echo "$RESPONSE" | jq -e '.errors' > /dev/null 2>&1; then + echo -e "${RED}Error querying Forge:${NC}" + echo "$RESPONSE" | jq -r '.errors[]' + exit 1 +fi + +# Display trackers +if [[ "$QUERY_TYPE" == "trackers" || "$QUERY_TYPE" == "all" ]]; then + echo -e "${GREEN}=== Trackers ===${NC}" + echo "" + echo "$RESPONSE" | jq -r '.project.trackers[] | "\(.id)\t\(.name)"' | \ + awk -F'\t' '{printf " %-4s %s\n", $1, $2}' + echo "" +fi + +# Display categories +if [[ "$QUERY_TYPE" == "categories" || "$QUERY_TYPE" == "all" ]]; then + echo -e "${GREEN}=== Issue Categories ===${NC}" + echo "" + echo "$RESPONSE" | jq -r '.project.issue_categories[] | "\(.id)\t\(.name)"' | \ + awk -F'\t' '{printf " %-6s %s\n", $1, $2}' + echo "" +fi + +# Display usage examples +if [[ "$QUERY_TYPE" == "all" ]]; then + echo -e "${BLUE}=== Usage Examples ===${NC}" + echo "" + echo "Create bug in Backend API category:" + echo ' curl -X POST \' + echo ' -H "Content-Type: application/json" \' + echo ' -H "X-Redmine-API-Key: $FORGE_API_KEY" \' + echo ' -d '"'"'{' + echo ' "issue": {' + echo ' "project_id": "typo3cms-core",' + echo ' "subject": "Issue title",' + echo ' "description": "Description",' + echo ' "tracker_id": 1,' + echo ' "category_id": 971,' + echo ' "priority_id": 4,' + echo ' "custom_fields": [{"id": 4, "value": "13"}]' + echo ' }' + echo ' }'"'"' \' + echo ' https://forge.typo3.org/issues.json' + echo "" + echo "Or use the interactive script:" + echo " ./scripts/create-forge-issue.sh" + echo "" +fi + +# Save to file if requested +if [[ "$2" == "--save" ]]; then + OUTPUT_FILE="forge-metadata-$(date +%Y%m%d).json" + echo "$RESPONSE" > "$OUTPUT_FILE" + echo -e "${GREEN}Metadata saved to: $OUTPUT_FILE${NC}" +fi diff --git a/scripts/setup-typo3-coredev.sh b/scripts/setup-typo3-coredev.sh new file mode 100755 index 0000000..cb32254 --- /dev/null +++ b/scripts/setup-typo3-coredev.sh @@ -0,0 +1,433 @@ +#!/bin/bash +# TYPO3 Core Development Environment Setup Script +# Based on proven production workflow +# Creates complete DDEV-based TYPO3 Core development environment + +set -e + +# Colors +GREEN='\033[0;32m' +BLUE='\033[0;34m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' # No Color + +# Print functions +print_header() { + echo -e "\n${BLUE}===================================================${NC}" + echo -e "${BLUE}$1${NC}" + echo -e "${BLUE}===================================================${NC}\n" +} + +print_step() { + echo -e "${GREEN}➜${NC} $1" +} + +print_info() { + echo -e "${YELLOW}ℹ${NC} $1" +} + +print_error() { + echo -e "${RED}✗${NC} $1" +} + +print_success() { + echo -e "${GREEN}✓${NC} $1" +} + +# Check prerequisites +check_prerequisites() { + print_header "Checking Prerequisites" + + local missing_prereqs=false + + # Check Git + if command -v git &> /dev/null; then + print_success "Git: $(git --version)" + else + print_error "Git not found. Please install Git first." + missing_prereqs=true + fi + + # Check DDEV + if command -v ddev &> /dev/null; then + print_success "DDEV: $(ddev version | head -n1)" + else + print_error "DDEV not found. Please install DDEV first: https://ddev.readthedocs.io/" + missing_prereqs=true + fi + + # Check Docker + if command -v docker &> /dev/null; then + if docker ps &> /dev/null; then + print_success "Docker: Running" + else + print_error "Docker not running. Please start Docker." + missing_prereqs=true + fi + else + print_error "Docker not found. DDEV requires Docker." + missing_prereqs=true + fi + + if [ "$missing_prereqs" = true ]; then + print_error "Missing prerequisites. Please install required tools and try again." + exit 1 + fi +} + +# Gather user input +gather_input() { + print_header "Configuration" + + # Project name + read -p "Project name (e.g., t3coredev-14-php8-4): " PROJECT_NAME + if [ -z "$PROJECT_NAME" ]; then + PROJECT_NAME="t3coredev-14-php8-4" + print_info "Using default: $PROJECT_NAME" + fi + + # Git user name + read -p "Your name for Git commits: " GIT_NAME + while [ -z "$GIT_NAME" ]; do + print_error "Name is required" + read -p "Your name for Git commits: " GIT_NAME + done + + # Git email + read -p "Your email for Git commits: " GIT_EMAIL + while [ -z "$GIT_EMAIL" ]; do + print_error "Email is required" + read -p "Your email for Git commits: " GIT_EMAIL + done + + # Gerrit username + read -p "Your Gerrit username (review.typo3.org): " GERRIT_USER + while [ -z "$GERRIT_USER" ]; do + print_error "Gerrit username is required" + read -p "Your Gerrit username: " GERRIT_USER + done + + # PHP version + read -p "PHP version (8.2, 8.3, 8.4) [default: 8.4]: " PHP_VERSION + if [ -z "$PHP_VERSION" ]; then + PHP_VERSION="8.4" + fi + + # Timezone + read -p "Timezone [default: Europe/Vienna]: " TIMEZONE + if [ -z "$TIMEZONE" ]; then + TIMEZONE="Europe/Vienna" + fi + + # Admin password + read -sp "TYPO3 admin password: " ADMIN_PASSWORD + echo + while [ -z "$ADMIN_PASSWORD" ]; do + print_error "Admin password is required" + read -sp "TYPO3 admin password: " ADMIN_PASSWORD + echo + done + + # Confirm + echo -e "\n${YELLOW}Configuration Summary:${NC}" + echo " Project: $PROJECT_NAME" + echo " Git Name: $GIT_NAME" + echo " Git Email: $GIT_EMAIL" + echo " Gerrit User: $GERRIT_USER" + echo " PHP Version: $PHP_VERSION" + echo " Timezone: $TIMEZONE" + echo + + read -p "Proceed with setup? (y/n): " CONFIRM + if [[ ! "$CONFIRM" =~ ^[Yy]$ ]]; then + print_info "Setup cancelled." + exit 0 + fi +} + +# Create project directory +create_project_dir() { + print_header "Creating Project Directory" + + if [ -d "$PROJECT_NAME" ]; then + print_error "Directory $PROJECT_NAME already exists!" + read -p "Delete and recreate? (y/n): " DELETE_CONFIRM + if [[ "$DELETE_CONFIRM" =~ ^[Yy]$ ]]; then + rm -rf "$PROJECT_NAME" + print_success "Deleted existing directory" + else + print_error "Cannot proceed with existing directory" + exit 1 + fi + fi + + mkdir -p "$PROJECT_NAME" + cd "$PROJECT_NAME" + print_success "Created and entered directory: $PROJECT_NAME" +} + +# Clone TYPO3 repository +clone_repository() { + print_header "Cloning TYPO3 Repository" + + print_step "Cloning from GitHub..." + if git clone git@github.com:typo3/typo3 . 2>&1 | grep -q "Permission denied\|Could not"; then + print_error "Failed to clone via SSH. Trying HTTPS..." + rm -rf .git + if ! git clone https://github.com/typo3/typo3.git . ; then + print_error "Failed to clone repository" + exit 1 + fi + fi + + print_success "Repository cloned successfully" +} + +# Configure Git +configure_git() { + print_header "Configuring Git" + + print_step "Setting user identity..." + git config user.name "$GIT_NAME" + git config user.email "$GIT_EMAIL" + print_success "User identity configured" + + print_step "Enabling automatic rebase..." + git config branch.autosetuprebase remote + print_success "Automatic rebase enabled" + + print_step "Installing git hooks..." + if [ -f "Build/git-hooks/commit-msg" ]; then + cp Build/git-hooks/commit-msg .git/hooks/commit-msg + chmod +x .git/hooks/commit-msg + print_success "Commit-msg hook installed" + else + print_error "Commit-msg hook not found in Build/git-hooks/" + fi + + print_step "Configuring Gerrit remote..." + git config remote.origin.pushurl "ssh://${GERRIT_USER}@review.typo3.org:29418/Packages/TYPO3.CMS.git" + git config remote.origin.push "+refs/heads/main:refs/for/main" + print_success "Gerrit remote configured" + + # Test Gerrit connection + print_step "Testing Gerrit SSH connection..." + if timeout 5 ssh -p 29418 -o StrictHostKeyChecking=no -o BatchMode=yes "${GERRIT_USER}@review.typo3.org" gerrit version &>/dev/null; then + print_success "Gerrit connection successful" + else + print_error "Cannot connect to Gerrit. Please verify your SSH keys are configured." + print_info "Continue anyway? SSH key might need configuration." + read -p "Continue? (y/n): " CONTINUE + if [[ ! "$CONTINUE" =~ ^[Yy]$ ]]; then + exit 1 + fi + fi +} + +# Configure DDEV +configure_ddev() { + print_header "Configuring DDEV" + + print_step "Setting project type..." + ddev config --project-type typo3 -y + + print_step "Configuring timezone..." + ddev config --timezone "$TIMEZONE" + + print_step "Setting PHP version..." + ddev config --php-version="$PHP_VERSION" + + print_step "Configuring webserver..." + ddev config --webserver-type=apache-fpm + + print_step "Setting database version..." + ddev config --database=mariadb:10.6 + + print_step "Adding environment variables..." + ddev config --web-environment-add="TYPO3_CONTEXT=Development/Ddev" + ddev config --web-environment-add="COMPOSER_ROOT_VERSION=14.0.x-dev" + + print_success "DDEV configured successfully" +} + +# Start DDEV +start_ddev() { + print_header "Starting DDEV" + + print_step "Starting containers..." + if ddev start; then + print_success "DDEV started successfully" + ddev describe + else + print_error "Failed to start DDEV" + exit 1 + fi +} + +# Install dependencies +install_dependencies() { + print_header "Installing Dependencies" + + print_step "Running Composer install via runTests.sh..." + if ./Build/Scripts/runTests.sh -s composerInstall; then + print_success "Dependencies installed" + else + print_error "Failed to install dependencies" + print_info "Trying alternative method..." + if ddev composer install; then + print_success "Dependencies installed via ddev composer" + else + print_error "Failed to install dependencies" + exit 1 + fi + fi +} + +# Setup TYPO3 +setup_typo3() { + print_header "Setting Up TYPO3" + + print_step "Creating installation trigger files..." + ddev exec 'touch /var/www/html/FIRST_INSTALL' + ddev exec 'touch /var/www/html/typo3conf/ENABLE_INSTALL_TOOL' + ddev exec 'echo "KEEP_FILE" > /var/www/html/typo3conf/ENABLE_INSTALL_TOOL' + print_success "Trigger files created" + + print_step "Running TYPO3 setup..." + if ddev typo3 setup \ + --driver=mysqli \ + --host=db \ + --port=3306 \ + --dbname=db \ + --username=db \ + --password=db \ + --admin-username=backenduser \ + --admin-user-password="$ADMIN_PASSWORD" \ + --admin-email="$GIT_EMAIL" \ + --project-name="TYPO3 Core Dev v14 PHP ${PHP_VERSION}" \ + --no-interaction \ + --server-type=apache \ + --force; then + print_success "TYPO3 setup completed" + else + print_error "TYPO3 setup failed" + exit 1 + fi +} + +# Activate extensions +activate_extensions() { + print_header "Activating Extensions" + + print_step "Setting up extensions..." + ddev typo3 extension:setup + + print_step "Activating indexed_search..." + ddev typo3 extension:activate indexed_search + + print_step "Activating styleguide..." + ddev typo3 extension:activate styleguide + + print_step "Activating scheduler..." + ddev typo3 extension:activate scheduler + + print_success "Extensions activated" +} + +# Setup backend groups +setup_backend_groups() { + print_header "Setting Up Backend User Groups" + + print_step "Creating default backend groups..." + if ddev typo3 setup:begroups:default --groups=Both; then + print_success "Backend groups configured" + else + print_error "Failed to setup backend groups" + fi +} + +# Generate test data +generate_test_data() { + print_header "Generating Test Data" + + read -p "Generate styleguide test data? (y/n): " GENERATE_DATA + if [[ "$GENERATE_DATA" =~ ^[Yy]$ ]]; then + print_step "Generating TCA examples..." + ddev typo3 styleguide:generate --create -- tca + + print_step "Generating frontend system template..." + ddev typo3 styleguide:generate --create -- frontend-systemplate + + print_success "Test data generated" + else + print_info "Skipping test data generation" + fi +} + +# Final steps +finalize() { + print_header "Setup Complete!" + + print_success "TYPO3 Core development environment is ready!" + echo + echo -e "${GREEN}Project Details:${NC}" + echo " Name: $PROJECT_NAME" + echo " URL: https://${PROJECT_NAME}.ddev.site" + echo " Backend: https://${PROJECT_NAME}.ddev.site/typo3" + echo " Admin User: backenduser" + echo " Admin Password: [the password you entered]" + echo + echo -e "${GREEN}Next Steps:${NC}" + echo " 1. Open backend: ddev launch /typo3" + echo " 2. Run tests: ./Build/Scripts/runTests.sh -s unit" + echo " 3. Create branch: git checkout -b feature/your-feature" + echo " 4. Make changes and commit with proper message" + echo " 5. Push to Gerrit: git push origin HEAD:refs/for/main" + echo + echo -e "${GREEN}Useful Commands:${NC}" + echo " ddev start - Start project" + echo " ddev stop - Stop project" + echo " ddev restart - Restart project" + echo " ddev ssh - SSH into container" + echo " ddev typo3 cache:flush - Clear TYPO3 caches" + echo " ddev logs -f - Follow logs" + echo + + read -p "Open TYPO3 backend now? (y/n): " OPEN_BACKEND + if [[ "$OPEN_BACKEND" =~ ^[Yy]$ ]]; then + ddev launch /typo3 + fi +} + +# Main execution +main() { + clear + print_header "TYPO3 Core Development Setup" + + echo "This script will set up a complete TYPO3 Core development environment." + echo "It will:" + echo " - Clone TYPO3 Core repository" + echo " - Configure Git for Gerrit submissions" + echo " - Set up DDEV with optimal settings" + echo " - Install TYPO3 with test data" + echo " - Activate development extensions" + echo + + check_prerequisites + gather_input + create_project_dir + clone_repository + configure_git + configure_ddev + start_ddev + install_dependencies + setup_typo3 + activate_extensions + setup_backend_groups + generate_test_data + finalize +} + +# Run main function +main diff --git a/scripts/validate-commit-message.py b/scripts/validate-commit-message.py new file mode 100755 index 0000000..14f7c54 --- /dev/null +++ b/scripts/validate-commit-message.py @@ -0,0 +1,256 @@ +#!/usr/bin/env python3 +""" +TYPO3 Commit Message Validator +Validates commit messages against TYPO3 contribution standards +""" + +import sys +import re +import argparse +from typing import List, Tuple + + +VALID_TYPES = ['BUGFIX', 'FEATURE', 'TASK', 'DOCS', 'SECURITY'] +BREAKING_PREFIX = '[!!!]' + + +class CommitMessageValidator: + def __init__(self, message: str): + self.message = message + self.lines = message.split('\n') + self.errors = [] + self.warnings = [] + + def validate(self) -> Tuple[bool, List[str], List[str]]: + """Run all validation checks""" + self.check_subject_line() + self.check_blank_line() + self.check_footer() + self.check_change_id() + + return len(self.errors) == 0, self.errors, self.warnings + + def check_subject_line(self): + """Validate the subject line""" + if not self.lines: + self.errors.append("Commit message is empty") + return + + subject = self.lines[0] + + # Check for commit type + type_pattern = r'^\[(?:\[!!!\])?(BUGFIX|FEATURE|TASK|DOCS|SECURITY)\]' + match = re.match(type_pattern, subject) + + if not match: + self.errors.append( + f"Subject must start with commit type: {', '.join(f'[{t}]' for t in VALID_TYPES)}" + ) + return + + commit_type = match.group(1) + + # Check for breaking change prefix + if subject.startswith('[!!!]'): + if commit_type == 'BUGFIX': + self.warnings.append( + "Breaking changes are unusual for BUGFIX. Consider using FEATURE or TASK" + ) + + # Extract subject without type prefix + subject_without_type = re.sub(type_pattern, '', subject).strip() + + # Check length + if len(subject) > 72: + self.errors.append( + f"Subject line is {len(subject)} characters (max 72). Current: {len(subject)}" + ) + elif len(subject) > 52: + self.warnings.append( + f"Subject line is {len(subject)} characters (recommended max 52)" + ) + + # Check capitalization + if subject_without_type and not subject_without_type[0].isupper(): + self.errors.append("Subject description must start with uppercase letter") + + # Check for period at end + if subject.endswith('.'): + self.errors.append("Subject line should not end with a period") + + # Check for imperative mood (heuristic) + if subject_without_type: + first_word = subject_without_type.split()[0].lower() + if first_word.endswith('ed') or first_word.endswith('ing'): + self.warnings.append( + f"Use imperative mood: '{first_word}' may not be imperative. " + "Use 'Fix' not 'Fixed' or 'Fixing'" + ) + + def check_blank_line(self): + """Check for blank line after subject""" + if len(self.lines) < 2: + return # Only subject line, no body + + if len(self.lines) >= 2 and self.lines[1] != '': + self.errors.append("Second line must be blank (separate subject from body)") + + def check_footer(self): + """Check footer tags""" + footer_pattern = r'^(Resolves|Related|Releases|Depends|Reverts):\s*' + + has_resolves = False + has_releases = False + has_change_id = False + + for i, line in enumerate(self.lines): + if re.match(footer_pattern, line): + # Check format: should have colon followed by space + if not re.match(r'^[A-Z][a-z]+:\s+', line): + self.errors.append( + f"Line {i+1}: Footer tag must have colon followed by space: '{line}'" + ) + + # Check specific tags + if line.startswith('Resolves:'): + has_resolves = True + # Validate issue number format + if not re.match(r'^Resolves:\s+#\d+', line): + self.errors.append( + f"Line {i+1}: Resolves must reference issue number: 'Resolves: #12345'" + ) + + elif line.startswith('Related:'): + if not re.match(r'^Related:\s+#\d+', line): + self.errors.append( + f"Line {i+1}: Related must reference issue number: 'Related: #12345'" + ) + + elif line.startswith('Releases:'): + has_releases = True + # Validate releases format + releases_value = line.split(':', 1)[1].strip() + releases = [r.strip() for r in releases_value.split(',')] + for release in releases: + if release != 'main' and not re.match(r'^\d+\.\d+$', release): + self.errors.append( + f"Line {i+1}: Invalid release format '{release}'. " + "Use 'main' or version like '13.4'" + ) + + elif line.startswith('Change-Id:'): + has_change_id = True + + # Warnings for missing tags + if not has_resolves: + self.warnings.append( + "No 'Resolves: #' tag found. Required for features and tasks." + ) + + if not has_releases: + self.warnings.append( + "No 'Releases:' tag found. Required to specify target versions." + ) + + def check_change_id(self): + """Check for Change-Id""" + change_id_pattern = r'^Change-Id:\s+I[a-f0-9]{40}$' + has_change_id = any(re.match(change_id_pattern, line) for line in self.lines) + + if not has_change_id: + self.warnings.append( + "No Change-Id found. It will be added automatically by git commit-msg hook." + ) + + def check_line_length(self): + """Check body line lengths""" + for i, line in enumerate(self.lines[2:], start=3): # Skip subject and blank line + if line.startswith(('Resolves:', 'Related:', 'Releases:', 'Change-Id:', 'Depends:', 'Reverts:')): + continue # Skip footer + + if len(line) > 72: + # Allow URLs to be longer + if not re.search(r'https?://', line): + self.warnings.append( + f"Line {i}: Length {len(line)} exceeds 72 characters" + ) + + +def main(): + parser = argparse.ArgumentParser( + description='Validate TYPO3 commit messages', + formatter_class=argparse.RawDescriptionHelpFormatter + ) + + parser.add_argument('--file', '-f', help='File containing commit message') + parser.add_argument('--message', '-m', help='Commit message string') + parser.add_argument('--strict', action='store_true', + help='Treat warnings as errors') + + args = parser.parse_args() + + # Get message + if args.file: + try: + with open(args.file, 'r') as f: + message = f.read() + except FileNotFoundError: + print(f"Error: File not found: {args.file}") + return 1 + elif args.message: + message = args.message + else: + # Read from last commit + try: + import subprocess + result = subprocess.run( + ['git', 'log', '-1', '--pretty=%B'], + capture_output=True, + text=True, + check=True + ) + message = result.stdout + except subprocess.CalledProcessError: + print("Error: Could not read last commit message") + print("Usage: Provide --file or --message, or run in a git repository") + return 1 + + # Validate + validator = CommitMessageValidator(message) + is_valid, errors, warnings = validator.validate() + + # Print results + print("=" * 60) + print("TYPO3 Commit Message Validation") + print("=" * 60) + print() + + if errors: + print("❌ ERRORS:") + for error in errors: + print(f" • {error}") + print() + + if warnings: + print("⚠️ WARNINGS:") + for warning in warnings: + print(f" • {warning}") + print() + + if not errors and not warnings: + print("✅ Commit message is valid!") + elif not errors: + print("✅ No errors found (warnings can be ignored)") + else: + print("❌ Validation failed. Please fix errors above.") + + print("=" * 60) + + # Exit code + if errors or (args.strict and warnings): + return 1 + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/scripts/verify-prerequisites.sh b/scripts/verify-prerequisites.sh new file mode 100755 index 0000000..1c15888 --- /dev/null +++ b/scripts/verify-prerequisites.sh @@ -0,0 +1,181 @@ +#!/bin/bash +# TYPO3 Core Contribution Prerequisites Checker +# Verifies accounts, git configuration, and development environment setup + +set -e + +# Colors for output +GREEN='\033[0;32m' +RED='\033[0;31m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +echo "================================================" +echo "TYPO3 Core Contribution Prerequisites Check" +echo "================================================" +echo + +# Track overall status +ALL_CHECKS_PASSED=true + +# Function to print status +print_status() { + if [ "$1" = "pass" ]; then + echo -e "${GREEN}✓${NC} $2" + elif [ "$1" = "fail" ]; then + echo -e "${RED}✗${NC} $2" + ALL_CHECKS_PASSED=false + elif [ "$1" = "warn" ]; then + echo -e "${YELLOW}⚠${NC} $2" + fi +} + +# 1. Check Git installation +echo "1. Checking Git installation..." +if command -v git &> /dev/null; then + GIT_VERSION=$(git --version) + print_status "pass" "Git installed: $GIT_VERSION" +else + print_status "fail" "Git not installed" +fi +echo + +# 2. Check Git user configuration +echo "2. Checking Git user configuration..." +GIT_USER_NAME=$(git config --global user.name 2>/dev/null || echo "") +GIT_USER_EMAIL=$(git config --global user.email 2>/dev/null || echo "") + +if [ -n "$GIT_USER_NAME" ] && [ -n "$GIT_USER_EMAIL" ]; then + print_status "pass" "Git user configured: $GIT_USER_NAME <$GIT_USER_EMAIL>" +else + print_status "fail" "Git user not configured. Run:" + echo " git config --global user.name \"Your Name\"" + echo " git config --global user.email \"your-email@example.org\"" +fi +echo + +# 2a. Verify Git email matches Gerrit account +echo "2a. Verifying Git email against Gerrit..." +if [ -n "$GIT_USER_EMAIL" ]; then + echo " Your Git email: $GIT_USER_EMAIL" + print_status "warn" " IMPORTANT: Verify this email is registered at:" + echo " https://review.typo3.org/settings#EmailAddresses" + echo " Gerrit will reject pushes if email doesn't match!" +fi +echo + +# 3. Check if in TYPO3 repository +echo "3. Checking TYPO3 repository..." +if [ -d ".git" ]; then + REPO_URL=$(git config --get remote.origin.url 2>/dev/null || echo "") + if [[ "$REPO_URL" == *"typo3"* ]]; then + print_status "pass" "In TYPO3 repository" + + # Check TYPO3-specific git config + echo " Checking TYPO3-specific configuration..." + + # Check auto-rebase + AUTO_REBASE=$(git config --get branch.autosetuprebase 2>/dev/null || echo "") + if [ "$AUTO_REBASE" = "remote" ]; then + print_status "pass" " Auto-rebase configured" + else + print_status "fail" " Auto-rebase not configured. Run: git config branch.autosetuprebase remote" + fi + + # Check Gerrit push URL + PUSH_URL=$(git config --get remote.origin.pushurl 2>/dev/null || echo "") + if [[ "$PUSH_URL" == *"review.typo3.org"* ]]; then + print_status "pass" " Gerrit push URL configured" + else + print_status "fail" " Gerrit push URL not configured. Run:" + echo " git config remote.origin.pushurl ssh://@review.typo3.org:29418/Packages/TYPO3.CMS.git" + fi + + # Check push refspec + PUSH_REFSPEC=$(git config --get remote.origin.push 2>/dev/null || echo "") + if [[ "$PUSH_REFSPEC" == *"refs/for/main"* ]]; then + print_status "pass" " Push refspec configured for Gerrit" + else + print_status "fail" " Push refspec not configured. Run:" + echo " git config remote.origin.push +refs/heads/main:refs/for/main" + fi + + else + print_status "warn" "In git repository but not TYPO3. URL: $REPO_URL" + fi +else + print_status "warn" "Not in a git repository (run from TYPO3 repo root)" +fi +echo + +# 4. Check Git hooks +echo "4. Checking Git hooks..." +if [ -f ".git/hooks/commit-msg" ]; then + print_status "pass" "commit-msg hook installed" +else + print_status "fail" "commit-msg hook not installed. Run: composer gerrit:setup" +fi + +if [ -f ".git/hooks/pre-commit" ]; then + print_status "pass" "pre-commit hook installed" +else + print_status "warn" "pre-commit hook not installed (optional but recommended)" +fi +echo + +# 5. Check SSH connection to Gerrit +echo "5. Checking Gerrit SSH connection..." +if timeout 5 ssh -p 29418 -o StrictHostKeyChecking=no -o BatchMode=yes review.typo3.org gerrit version &>/dev/null; then + print_status "pass" "Gerrit SSH connection successful" +else + print_status "fail" "Cannot connect to Gerrit via SSH. Check your SSH keys and Gerrit setup" +fi +echo + +# 6. Check Composer +echo "6. Checking Composer installation..." +if command -v composer &> /dev/null; then + COMPOSER_VERSION=$(composer --version 2>/dev/null | head -n1) + print_status "pass" "Composer installed: $COMPOSER_VERSION" +else + print_status "warn" "Composer not found (needed for running tests and gerrit:setup)" +fi +echo + +# 7. Check PHP +echo "7. Checking PHP installation..." +if command -v php &> /dev/null; then + PHP_VERSION=$(php -v | head -n1) + print_status "pass" "PHP installed: $PHP_VERSION" +else + print_status "warn" "PHP not found (needed for development and testing)" +fi +echo + +# 8. Check DDEV (optional) +echo "8. Checking DDEV installation (optional)..." +if command -v ddev &> /dev/null; then + DDEV_VERSION=$(ddev version | head -n1) + print_status "pass" "DDEV installed: $DDEV_VERSION" +else + print_status "warn" "DDEV not found (recommended for development environment)" +fi +echo + +# Final Summary +echo "================================================" +if [ "$ALL_CHECKS_PASSED" = true ]; then + echo -e "${GREEN}✓ All critical checks passed!${NC}" + echo "You're ready to contribute to TYPO3 Core." +else + echo -e "${RED}✗ Some checks failed.${NC}" + echo "Please address the issues above before contributing." +fi +echo "================================================" + +# Exit with appropriate code +if [ "$ALL_CHECKS_PASSED" = true ]; then + exit 0 +else + exit 1 +fi