Skip to content

feat: add deploy:writable:chmod task for proper file permissions - #14

Merged
konradmichalik merged 5 commits into
mainfrom
feature/deploy-writable-chmod
Feb 18, 2026
Merged

feat: add deploy:writable:chmod task for proper file permissions#14
konradmichalik merged 5 commits into
mainfrom
feature/deploy-writable-chmod

Conversation

@konradmichalik

@konradmichalik konradmichalik commented Feb 18, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add shared applyDeployPermissions() function for standardized file/directory permissions
  • Add deploy:writable:chmod task for TYPO3 (new) and refactor existing Symfony task
  • Fix Symfony config: writable_chmod_mode from 0770 to 2770, correct writable_recursive key name

Problem

The standard deploy:writable task only applies a flat chmod on writable_dirs without differentiating between files and directories. This causes permission issues in TYPO3 (and Symfony) projects:

  • No SGID bit for group inheritance on directories
  • No separation of file (644) vs directory (2755) permissions
  • var/cache not created before cache warmup
  • TYPO3 CLI binary not made executable
  • Shared directory permissions never corrected after initial setup

Changes

  • deployer/functions.php - New applyDeployPermissions() with configurable modes and fallback defaults
  • deployer/typo3/task/deploy_writable_chmod.php - New TYPO3 task (calls shared function + CLI binary chmod)
  • deployer/typo3/task/deploy.php - Add task to deploy sequence after deploy:writable
  • deployer/typo3/autoload.php - Register new task file
  • deployer/typo3/config/set.php - Add writable_chmod_mode_files, writable_chmod_mode_dirs, writable_chmod_mode_writable_dirs
  • deployer/symfony/task/deploy_writable_chmod.php - Refactored to use shared function
  • deployer/symfony/config/set.php - Fix chmod mode to 2770, fix dead writable_chmod_recursive key, add new config vars

Summary by CodeRabbit

  • New Features

    • Introduced granular file and directory permission controls during deployments, allowing separate and configurable permission settings for different file types and writable directories.
    • Enhanced TYPO3 deployments with automatic permission adjustment for CLI utilities and executable binaries.
  • Chores

    • Refactored permission handling to centralize file and directory permission management across deployment frameworks for improved consistency.

@coderabbitai

coderabbitai Bot commented Feb 18, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@konradmichalik has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 17 minutes and 1 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📝 Walkthrough

Walkthrough

Introduces a centralized applyDeployPermissions() function to standardize file and directory permission handling during deployments. Refactors Symfony and TYPO3 deployment tasks to use this function instead of inline chmod commands. Adds granular permission configuration options for distinguishing between file permissions, directory permissions, and writable directory permissions across both frameworks.

Changes

Cohort / File(s) Summary
Core Permission Function
deployer/functions.php
Adds new applyDeployPermissions() function implementing centralized permission management with configurable modes for files (644), directories (2755), and writable directories (2775); handles var/cache creation, SGID-aware directory permissions, and recursive writable access.
Symfony Configuration & Task
deployer/symfony/config/set.php, deployer/symfony/task/deploy_writable_chmod.php
Replaces writable_chmod_mode and writable_chmod_recursive with granular permission settings (writable_chmod_mode_files, writable_chmod_mode_dirs, writable_chmod_mode_writable_dirs); refactors task to delegate to centralized permission function.
TYPO3 Configuration & Integration
deployer/typo3/config/set.php, deployer/typo3/autoload.php, deployer/typo3/task/deploy.php
Adds granular permission configuration settings; registers deploy_writable_chmod task in autoload; integrates task into deployment sequence after writable step.
TYPO3 Permission Task
deployer/typo3/task/deploy_writable_chmod.php
New deployment task that applies centralized permissions via applyDeployPermissions() and additionally ensures TYPO3 CLI binaries (typo3, typo3cms) are executable.

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly Related PRs

  • feat: add cache warmup #2: Modifies deployer/typo3/autoload.php to add task autoloading and introduces TYPO3-specific deployment enhancements in the same framework integration area.

Poem

🐰 Permissions now flow through one central gate,
No more scattered chmod, let's standardize our fate!
Files and dirs get their own careful way,
TYPO3 binaries leap with executable play. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: introducing a new deploy:writable:chmod task for handling file permissions during deployment, which is the primary feature across all modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/deploy-writable-chmod

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@deployer/functions.php`:
- Around line 169-170: The current runExtended("cd {{ deploy_path }}/shared &&
find . -type f -exec chmod $modeFiles {} +") makes all files (including
shared/.env or shared/.env.local) world-readable; after keeping that baseline
chmod call, add a second step that iterates over the shared_files array and
tightens permissions for sensitive entries (e.g., runExtended calls that chmod
600 or 640 specifically for each path in shared_files or for patterns like .env
and .env.local), referencing the existing runExtended invocation and the
shared_files variable so only those sensitive files get stricter permissions.
- Around line 163-166: The recursive chmod call in runExtended("cd {{
release_path }} && chmod -R $modeWritableDirs var/cache") wrongly applies
directory bits (SGID/execute) to files; change the deployment step so
runExtended leaves files set by runExtended("cd {{ release_path }} && find .
-type f -exec chmod $modeFiles {} +") and only applies $modeWritableDirs to
directories under var/cache (e.g. use find to target -type d for var/cache or a
non-recursive chmod on the dir itself) so that $modeFiles (644) remains on cache
files while directories get the writable/SUID bits; update the runExtended
invocation(s) around the var/cache handling accordingly (refer to the existing
runExtended calls and $modeFiles/$modeWritableDirs variables).
- Around line 160-177: The current permission sweep uses runExtended with
$modeDirs/$modeFiles on the entire release tree, which downgrades release-only
writable directories set earlier; add a loop after the shared_dirs loop that
iterates get('writable_dirs') and for each $dir that exists under {{
release_path }} but is NOT listed in get('shared_dirs') run runExtended to
recursively set directory perms to $modeWritableDirs and file perms to the
writable file mode (use $modeWritableFiles or $modeFiles as appropriate) so
release-path-only writable dirs and their contained files are restored for
webserver write access; reference runExtended, get('writable_dirs'),
get('shared_dirs'), $modeWritableDirs and $modeWritableFiles/$modeFiles to
locate and apply the fix.

In `@deployer/symfony/config/set.php`:
- Around line 33-37: The change to set('writable_chmod_mode','2770') introduces
SGID and is a breaking change because deploy:writable will now chmod 2770 on
writable_dir; either revert the default back to '0770' (restore previous
behavior in set('writable_chmod_mode')) and add a migration note, or keep '2770'
but add a clear CHANGELOG / migration entry and upgrade note describing the new
SGID behavior and that deploy:writable will apply 2770 to writable_dir
(reference the config keys writable_chmod_mode,
writable_chmod_mode_writable_dirs and the deploy:writable task in the
changelog/migration doc).

Comment thread deployer/functions.php
Comment thread deployer/functions.php Outdated
Comment thread deployer/functions.php
Comment on lines +33 to +37
set('writable_chmod_mode', '2770');
set('writable_recursive', false);
set('writable_chmod_mode_files', '644');
set('writable_chmod_mode_dirs', '2755');
set('writable_chmod_mode_writable_dirs', '2775');

@coderabbitai coderabbitai Bot Feb 18, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

writable_chmod_mode change from 07702770 is a breaking behavior change.

Adding the SGID bit (2) is intentional per the PR, but deploy:writable will now run chmod 2770 on every writable_dir instead of chmod 0770. Existing projects upgrading this package will silently get a different permission mode applied to their writable dirs on the next deploy.

Consider documenting this in a CHANGELOG or migration note.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@deployer/symfony/config/set.php` around lines 33 - 37, The change to
set('writable_chmod_mode','2770') introduces SGID and is a breaking change
because deploy:writable will now chmod 2770 on writable_dir; either revert the
default back to '0770' (restore previous behavior in set('writable_chmod_mode'))
and add a migration note, or keep '2770' but add a clear CHANGELOG / migration
entry and upgrade note describing the new SGID behavior and that deploy:writable
will apply 2770 to writable_dir (reference the config keys writable_chmod_mode,
writable_chmod_mode_writable_dirs and the deploy:writable task in the
changelog/migration doc).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@coderabbitai Intentional change. The previous code had a TODO: // todo maybe change to '2770'. SGID is the core purpose of this PR. This is an internal tool where we control all deployments, so no separate changelog entry needed.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@konradmichalik, thank you for the clarification! You're absolutely right—the TODO comment confirms this was planned, and since this is an internal tool where you control all deployments, the breaking change concern doesn't apply. The SGID behavior is exactly what you need. I appreciate the context!

@konradmichalik
konradmichalik merged commit 02568d4 into main Feb 18, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant