Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 08:43:24 +08:00
commit e1d41c1e9f
22 changed files with 7231 additions and 0 deletions

275
references/account-setup.md Normal file
View File

@@ -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 <YOUR_USERNAME>@review.typo3.org
# Expected output:
# **** Welcome to Gerrit Code Review ****
# Hi <Your Name>, 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 <username>@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 <user>@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 <user>@review.typo3.org` | Verify connection |
| Slack | https://typo3.slack.com | Community chat |
| Documentation | https://docs.typo3.org/m/typo3/guide-contributionworkflow/ | Full guide |

View File

@@ -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 |

View File

@@ -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<hash>` 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: #<number>` or `Fixes: #<number>`
- 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: #<issue number>' line.
```
**Updated Message** (as of v1.2, see Issue #107881):
```
You need at least one 'Resolves: #<issue number>' 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: #<issue number>' 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: #<issue number>' 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: <description>" >> .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: #<issue number>'`
- **New**: `'Resolves: #<issue number>'`
**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

View File

@@ -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 <project>
```
2. **Clean up old projects**:
```bash
ddev delete <project>
# 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.

436
references/forge-api.md Normal file
View File

@@ -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

View File

@@ -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.

View File

@@ -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 <conflicted_files>", 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 <file>..." 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://<username>@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 <user>@review.typo3.org` |

File diff suppressed because it is too large Load Diff