I recently found myself needing to change the user-group for file permissions depending on the connection being deployed to via Rocketeer. Rather than completely override the permissions callback
defined in remote.php for the specific context I wanted to be able to define the user-group as a configuration option that could be overridden contextually. It turns out this is pretty simple to achieve.
The default file permissions callback generated by rocketeer ignite
looks something like this:-
'callback' => function ($task, $file) {
return [
sprintf('chmod -R 755 %s', $file),
sprintf('chmod -R g+s %s', $file),
sprintf('chown -R www-data:www-data %s', $file),
];
},
The only line of this that I want to be able to change for a specific connection is:-
sprintf('chown -R www-data:www-data %s', $file),
Or more specifically I want to change the user-group from www-data:www-data
to apache:apache
for one of my connections.
With Rocketeer you can define custom options anywhere within the return arrays of the configuration files. So I created a user_group
option within the permissions
array of the remote.php configuration file:-
'user_group' => 'www-data:www-data',
The next thing to do was to read in this new custom option within the permissions callback
closure using the handy getOption()
method made available to the task via the rocketeer
object like this:-
$userGroup = $task->rocketeer->getOption('remote.permissions.user_group');
getOption()
takes a string representation of the array path of the option as its first parameter and returns the option set for the current context; the array path is defined as the array keys separated by dots (.
).
So my updated callback
now looks like:-
'callback' => function ($task, $file) {
$userGroup = $task->rocketeer->getOption('remote.permissions.user_group');
return [
sprintf('chmod -R 755 %s', $file),
sprintf('chmod -R g+s %s', $file),
sprintf('chown -R %s %s', $userGroup, $file),
];
},
My final permissions
array in remote.php looks like this:-
'permissions' => [
// The folders and files to set as web writable
'files' => [
'app/database/production.sqlite',
'storage',
'public',
],
'user_group' => 'www-data:www-data',
// Here you can configure what actions will be executed to set
// permissions on the folder above. The Closure can return
// a single command as a string or an array of commands
'callback' => function ($task, $file) {
$userGroup = $task->rocketeer->getOption('remote.permissions.user_group');
return [
sprintf('chmod -R 755 %s', $file),
sprintf('chmod -R g+s %s', $file),
sprintf('chown -R %s %s', $userGroup, $file),
];
},
],
I can now override the user-group for a connection by specifying user_group
in my contextual options for the connection in config.php as you would for any other option. For example:-
'on' => [
'connections' => [
'staging' => [
'remote' => [
'permissions' => [
'user_group' => 'apache:apache'
]
]
]
]
],
Now when I deploy to staging (rocketeer deploy --on="staging"
) it will use the user-group apache:apache
instead of the default www-data:www-data
.
With this approach rather than have to override the whole callback
closure for the connection I am just changing the user-group that needs to be different. As a result I am avoiding unnecessary duplication of code.
I hope that this has been helpful as it took me a little while to figure this out for myself; the official documentation didn’t seem to offer a solution to what I was attempting to achieve.
The ability to set custom Rocketeer options and get any defined option from within a closure is incredibly useful.