deployer icon indicating copy to clipboard operation
deployer copied to clipboard

Tasks selected for one host are run on other hosts at the same time as well, if the same task will run on other hosts later

Open SimJoSt opened this issue 2 years ago • 0 comments

  • Deployer version: https://github.com/deployphp/deployer/releases/tag/v7.3.1
  • Deployment OS: macOS Ventura 13.5.2

We were trying to build a 2 step deployment with a build step on a local host for the CI. So first we wanted to setup the build environment, perform the build, then prepare the server and then transfer everything with the rsync recipe. Everything worked wonderfully when the tasks were run one at a time.

In the end we put everything together under one deploy group task. We ran the task if performed most tasks on both hosts at the same time, even though it should only do the ci first and the server later. With some tinkering, we found the issue.

The tasks that should be run only on one of the hosts are extended with ->select(). This generally works. However, like it is mentioned in the docs for the cli regarding the exuction plan, all tasks are merged: https://deployer.org/docs/7.x/cli#execution-plan:~:text=Before%20executing%20tasks%2C%20Deployer%20needs%20to%20flatten%20the%20task%20tree%20and%20decide%20in%20which%20order%20it%20will%20be%20executing%20tasks%20on%20which%20hosts. The result is, that all tasks are run on both hosts even though restrictions are in place, as long as the same task is also defined for another hosts later. Only tasks that are only defined for one host will only run on that host.

For example, if we run deployer:prepare as part of the build task only on the ci host, it will also run on the remote host, as the task is defined in another group task later on for the deploy. The task npm:install is only defined for the ci host and will not run on the remote host.

Our understanding is, that the execution plan is not checking when a task should be run on a specific host. It just checks if that task will be run on any host at any time. And then it will run it on all hosts it is defined for at all times when it is called.

<?php
namespace Deployer;

require 'recipe/common.php';
require 'contrib/npm.php';

// Hosts

localhost('ci')
    ->set('labels', ['type' => 'ci']);
host('dev.example.com')
    ->set('labels', ['type' => 'remote']);

// Tasks

task('deploy', [
    'build',
    'deploy:server'
]);

task('build', [
    'build:prepare',
])->select('type=ci');

task('build:prepare', [
    'deploy:info',
    'deploy:prepare',
    'npm:install',
])->select('type=ci');

task('deploy:server', [
    'deploy:info',
    'deploy:prepare',
])->select('type=remote');
$ ./vendor/bin/dep deploy type=ci,type=remote --plan
┌────────────────────┬────────────────────┐
│ localhost          │ development        │
├────────────────────┼────────────────────┤
│ deploy:info        │ deploy:info        │
│ deploy:info        │ deploy:info        │
│ deploy:setup       │ deploy:setup       │
│ deploy:lock        │ deploy:lock        │
│ deploy:release     │ deploy:release     │
│ deploy:update_code │ deploy:update_code │
│ deploy:shared      │ deploy:shared      │
│ deploy:writable    │ deploy:writable    │
│ npm:install        │ -                  │
│ deploy:info        │ deploy:info        │
│ deploy:info        │ deploy:info        │
│ deploy:setup       │ deploy:setup       │
│ deploy:lock        │ deploy:lock        │
│ deploy:release     │ deploy:release     │
│ deploy:update_code │ deploy:update_code │
│ deploy:shared      │ deploy:shared      │
│ deploy:writable    │ deploy:writable    │
└────────────────────┴────────────────────┘

Upvote & Fund

  • We're using Polar.sh so you can upvote and help fund this issue.
  • We receive the funding once the issue is completed & confirmed by you.
  • Thank you in advance for helping prioritize & fund our backlog.
Fund with Polar

SimJoSt avatar Sep 22 '23 14:09 SimJoSt