Skip to content

v3.0.0#227

Open
lucatume wants to merge 65 commits intomainfrom
3.0.0
Open

v3.0.0#227
lucatume wants to merge 65 commits intomainfrom
3.0.0

Conversation

@lucatume
Copy link
Copy Markdown
Contributor

@lucatume lucatume commented Nov 18, 2025

This PR replaces the #225 one and builds on the multi-stacks support to implement worktree support.
If I read it correctly, this should also replace #220.

Multi-stack demo
Worktree support demo
Interactive use selection demo
shell completions demo - demo on zsh as that is the one I use

The two main feature in detail:

Multi-stack support

Assume there two plugin directories I'm working on:

  • /Users/lucatume/project-1/plugins, this has the plugin plugin-1 that has the wpunit suite
  • /Users/lucatuem/project-2/plugins, this has the plugin plugin-2 that has the integration suite

If I want to run the wpunit suite on plugin-1 in the first path, and the integration suite on plugin-2 in the second path, these are the before and after flows:

Before

cd /Users/lucatume/project-1/plugins
slic here
slic use plugin-1
slic run wpunit

Then wait for the tests to complete ...

cd /Users/lucatume/project-2/plugins
slic here
slic use plugin-2
slic run integration

Then wait for the tests to complete.

The context change introduced by the single slic stack is this:

cd <project_plugins_path>
slic here
slic use <project_target>

And it has to be done over and over for each context change, killing the possible benefit of working on other projects while long-runing operations (like tests) complete.

After

Same requirements, but:

cd /Users/lucatume/project-1/plugins
slic here
slic use plugin-1
slic run wpunit

Nothing changed in the commands I'm running, but now I do not need to wait for the tests to be done to run tests on another project.
In a new terminal tab/window:

cd /Users/lucatume/project-2/plugins
slic here
slic use plugin-2
slic run integration

I can keep running tests (and using slic shells and all other commands) without having to change context.

Deterministic stack names and XDebug ports

By default, docker would assign random names to the stacks created and would allocate random ports.
To avoid having to reconfigure the IDE on each slic down && slic up cycle, the multi-stack feature build the project name and XDebug remote port deterministically from the path of the stack.

I.e. the stack for /Users/Alice/acme/wp-content/plugins will have the same project name (slic_... that is also the XDebug server_name) and Xdebug remote port.
The xdebug commands have been updated to take that into account and provide the correct information depending on the stack.

Worktree support

Building on this multi-stack support, understanding the worktree support is easier.

For "worktree" here I mean the "git worktree" support; I will not delve into what git worktree does, but in very short terms it allows copying the repository to a linked directory; it replaces changing branch with changing directory.

Git branch vs worktree flow

This is required to understand how slic wraps the worktree functionality. To "ground" the example I will use the-events-calendar plugin located at /Users/lucatume/tec-dev/wp-content/plugins/the-events-calendar.

In this example I'm working on two issues: fix/issue-1 and fix/issue-2.

*With branches

cd /Users/lucatume/tec-dev/wp-content/plugins
slic here
slic use the-events-calendar
cd the-events-calendar
git checkout main
git checkout --branch fix/issue-1

Work on fix/issue-1, run some test using slic:

slic run wpunit

And when done change to fix/issue-2:

git checkout main
git checkout --branch fix/issue-2

Again work in fix/issue-2, run some tests and wrap the fix.

This is fine, but the use of worktrees could get rid of some lull times.

With git worktree

cd /Users/lucatume/tec-dev/wp-content/plugins
slic here
slic use the-events-calendar
cd the-events-calendar
git checkout main
git worktree add ../the-events-calendar-fix-issue-1 -b fix/issue-1
git worktree add ../the-events-calendar-fix-issue-2 -b fix/issue-2

This is the new directory structure:

/Users/lucatume/tec-dev/wp-content/plugins
  - the-events-calendar                    <- current slic target
  - the-events-calendar-fix-issue-1
  - the-events-calendar-fix-issue-2

To work on fix/issue-1 I would need to change target:

slic use the-events-calendar-fix-issue-1

BUT all the test files are set to use the-events-calendar directory (without the -fix-issue-1 postfix) and, in short, what I will be testing will always be the-events-calendar.

One thing to note is the volume binding done in the slic and wordpress services in the stack:

GUEST /Users/lucatume/tec-dev/wp-content/plugins -> HOST /var/www/html/wp-content/plugins

This means the directory structure will be reflected in the container:

/var/www/html/wp-content/plugins
  - the-events-calendar                    <- current slic target
  - the-events-calendar-fix-issue-1
  - the-events-calendar-fix-issue-2

So, worktree support is not really workable out of the box.

Slic worktree support

Slic wraps in very limited capacity some git worktree commands, notably for this example, the commnands will change to:

cd /Users/lucatume/tec-dev/wp-content/plugins
slic here
slic use the-events-calendar
cd the-events-calendar
git checkout main
slic worktree add fix/issue-1
slic worktree add fix/issue-2

The same directory structures have been created, but slic created a dedicated stack for each worktree under the hood.

This means this flow is now possible:

# Change to the the worktree fix/issue-1 directory.
cd /users/lucatume/tec-dev/wp-content/plugins/the-events-calendar-fix-issue-1

# Using the path slic knows what stack to use: the fix/issue-1 worktree one
slic run wpunit

cd /users/lucatume/tec-dev/wp-content/plugins/the-events-calendar-fix-issue-2
slic run integration

Notably, slic uses the "shadowing" provided by volume binding override to have these volume binds in the fix/issue-1 worktree:

GUEST /Users/lucatume/tec-dev/wp-content/plugins -> HOST /var/www/html/wp-content/plugins
GUEST /Users/lucatume/tec-dev/wp-content/plugins/the-events-calendar-fix-issue-1 -> HOST /var/www/html/wp-content/plugins/the-events-calendar
GUEST /Users/lucatume/tec-dev/wp-content/plugins/the-events-calendar-fix-issue-2 -> HOST /var/www/html/wp-content/plugins/the-events-calendar-fix-issue-2 (implicit from the plugins binding)

And these volume binds in the fix/issue-2 worktree:

GUEST /Users/lucatume/tec-dev/wp-content/plugins -> HOST /var/www/html/wp-content/plugins
GUEST /Users/lucatume/tec-dev/wp-content/plugins/the-events-calendar-fix-issue-1 -> HOST /var/www/html/wp-content/plugins/the-events-calendar-fix-issue-1 (implicit from the plugins binding)
GUEST /Users/lucatume/tec-dev/wp-content/plugins/the-events-calendar-fix-issue-2 -> HOST /var/www/html/wp-content/plugins/the-events-calendar

So the use target (the-events-calendar in this example) is actually from the worktree directory.

Wait! In the second example the fix/issue-1 worktree directory will still be bound in the container!

Yes, the same would be true for any other worktree. The idea is that having them there will not cause issues. WordPress uses the plugin directory name to identify the plugins, so they will be just like any other unused plugin directory.

The PR contains many more commands and changes, but all of them geared toward supporting this new features.

Tests

This PR contains the setup and scaffolding of PHPUnit tests as well. The complete body of tests is in #238.

@lucatume lucatume self-assigned this Nov 18, 2025
From a merge conflict
They are set at stack creation time, no need to wait for the containers
to run since the data is not managed by docker.
This fixes an issue where the first `stack info` command after a start
would not find the ports set
In the new system, the .env.slic.run file will always be loaded first,
then the stack env file if any, then the project local configuration
file. Some options like the CLI_VERBOSITY env var are still managed at
the whole application level and stored in the .env.slic.run file.
Merge the multi-stack and WSL2 concerns.
cli override > staged > project .env.slic.local > project slic.json >
stack config > slic default
xdebug_setup_env_vars() sets the XDK env var to the full stack-specific
key (e.g. "slic_a1dc6067") during bootstrap. When a second stack is
registered, slic_stacks_xdebug_server_name() read that contaminated
value via getenv('XDK') and appended another hash, producing incorrect
keys like "slic_a1dc6067_ac80b3a1" instead of "slic_ac80b3a1".
Suppress ANSI color codes and ASCII art banner when the NO_COLOR
environment variable is set, following the no-color.org convention.
Extract CLI_VERSION to version.php, add composer.json with PHPUnit
dependency, and set up tests/cli directory with a version validation
test and .phpt format reference.
Add docker_bin() function and replace all hardcoded docker binary
references. The docker_compose_bin() default now derives from
docker_bin() to keep both consistent.
Add PHPUnit test infrastructure for CLI
Add 13 new black-box tests covering all PHP version detection paths:
set/reset, staged versions, auto-detection from composer.json and
slic.json, CLI override, .env.slic.local override, priority ordering,
version normalization, and invalid format rejection.

Move shared helpers (dockerMockEnv, setUpPluginsDir) to BaseTestCase
and add tearDown stack cleanup to prevent orphaned registry entries.
@lucatume lucatume marked this pull request as ready for review February 26, 2026 11:00
@lucatume lucatume requested review from bordoni and defunctl February 26, 2026 11:00
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.

3 participants