Skip to content

N°9722 - Setup - extension dependencies must be computed with installation choice change#965

Merged
odain-cbd merged 16 commits into
developfrom
issue/9722-compil2
Jul 8, 2026
Merged

N°9722 - Setup - extension dependencies must be computed with installation choice change#965
odain-cbd merged 16 commits into
developfrom
issue/9722-compil2

Conversation

@eespie

@eespie eespie commented Jul 7, 2026

Copy link
Copy Markdown
Member

N°9722 - Setup - extension dependencies must be computed with installation choice change

Copilot AI review requested due to automatic review settings July 7, 2026 15:48
@CombodoApplicationsAccount CombodoApplicationsAccount added the internal Work made by Combodo label Jul 7, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR (N°9722) refactors iTop's setup/compilation pipeline so that extension dependencies (selected extensions and modules) are computed from the current installation choices before the data model is compiled, rather than after. It consolidates the compilation logic around DoCompile()/GetModulesToLoadFromChoices(), removes the now-obsolete DryRemovalRuntimeEnvironment "dry run" environment, and drops the older GetMFModulesToCompile()/GetDirsToCompile()/GetModulesToLoad()/GetExtraDirsToScan() machinery in favor of a single GetAdditionalMFModulesBeforeFinalDeltaToCompile() hook.

Changes:

  • Reworked RunTimeEnvironment::CompileFrom()/DoCompile() (now returns the selected modules) and simplified GetModulesToLoadFromChoices() to derive search dirs and choices internally.
  • Updated DataFeatureRemovalController to compute selected extensions/modules up front with a plain RunTimeEnvironment, and deleted DryRemovalRuntimeEnvironment plus its references.
  • Adjusted callers/tests (HubController, DataAuditSequencer, UnitTestRunTimeEnvironment) and commented out several tests in SetupAuditTest.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
setup/runtimeenv.class.inc.php Core refactor of compile pipeline; removes legacy helpers, adds GetAdditionalMFModulesBeforeFinalDeltaToCompile, changes signatures/returns. Docblock typo flagged.
setup/extensionsmap.class.inc.php Adds an empty GetSelectedModules() stub (flagged as dead code).
datamodels/2.x/combodo-data-feature-removal/src/Controller/DataFeatureRemovalController.php Computes selected extensions/modules before compile; adds unused IssueLog import (flagged).
datamodels/2.x/itop-hub-connector/src/Controller/HubController.php Drops now-unused return capture from CompileFrom.
setup/sequencers/DataAuditSequencer.php Removes unused source_dir/extensions_dir params.
setup/feature_removal/DryRemovalRuntimeEnvironment.php Deleted; no remaining references.
tests/php-unit-tests/src/Service/UnitTestRunTimeEnvironment.php Overrides new parent hook instead of old GetMFModulesToCompile.
tests/.../setup/feature_removal/SetupAuditTest.php Removes teardown and comments out three tests (flagged: maintainability/coverage).
tests/.../combodo-data-feature-removal/*.php Adds require_once for AbstractCleanup.php.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread setup/extensionsmap.class.inc.php Outdated
Comment thread setup/runtimeenv.class.inc.php Outdated
Comment thread tests/php-unit-tests/unitary-tests/setup/feature_removal/SetupAuditTest.php Outdated
Comment thread tests/php-unit-tests/unitary-tests/setup/feature_removal/SetupAuditTest.php Outdated
@greptile-apps

greptile-apps Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR refactors the setup compilation pipeline to remove the DryRemovalRuntimeEnvironment class and consolidate extension selection/dependency computation directly into RunTimeEnvironment, so that extension dependency recalculation responds correctly to user installation-choice changes during setup.

  • DryRemovalRuntimeEnvironment is deleted; CompileFrom/DoCompile/GetModulesToLoadFromChoices are rewritten to accept explicit extension and module lists, and CheckExtensionsValidity() is extracted from DoCompile into iTopExtensionsMap.
  • DataFeatureRemovalController now instantiates a plain RunTimeEnvironment and drives the compile/module-selection flow directly, computing selected extensions from DB choices adjusted for add/remove deltas before compilation.
  • Test infrastructure is updated to rename GetAdditionalFeaturePathsGetAdditionalExtensionsPaths and adapt UnitTestRunTimeEnvironment::CompileFrom to the new API.

Confidence Score: 3/5

Not safe to merge as-is: both RunTimeEnvironment::CompileFrom and UnitTestRunTimeEnvironment::CompileFrom call DoCompile with integer array indices instead of extension codes, causing compilation to produce an empty/wrong model.

In both CompileFrom implementations, GetSelectedExtensions returns a plain numerically-indexed list of extension code strings, but array_keys() is then applied before passing to DoCompile. DoCompile uses in_array($oExtension->sCode, $aSelectedExtensionCodes) to decide which extensions to mark as chosen — comparing string codes against integer indices always yields false in PHP 8, so the compiled model silently includes no extensions. This affects the HubController flow (installs), the unit test compilation path, and any other caller that goes through CompileFrom.

setup/runtimeenv.class.inc.php (CompileFrom) and tests/php-unit-tests/src/Service/UnitTestRunTimeEnvironment.php (CompileFrom override) both need array_keys() removed from the DoCompile call.

Important Files Changed

Filename Overview
setup/runtimeenv.class.inc.php Major refactoring of CompileFrom/DoCompile/GetModulesToLoadFromChoices; introduces a P1 bug where array_keys() on an indexed list of extension codes passes integer indices to DoCompile, causing all extensions to be treated as not chosen during compilation.
setup/extensionsmap.class.inc.php Adds CheckExtensionsValidity() method (extracted from DoCompile) and GetSelectedExtensions(); GetSelectedExtensions still crashes when GetChoicesFromDatabase returns false (already flagged externally).
datamodels/2.x/combodo-data-feature-removal/src/Controller/DataFeatureRemovalController.php Removes DryRemovalRuntimeEnvironment dependency; reorders compile/module selection logic; extension selection now computed before CopySetupFiles when first-run (ordering concern flagged externally).
tests/php-unit-tests/src/Service/UnitTestRunTimeEnvironment.php Adapts CompileFrom to new API; contains the same array_keys() P1 bug as RunTimeEnvironment::CompileFrom, causing test compilations to treat all extensions as not chosen.
tests/php-unit-tests/unitary-tests/setup/feature_removal/SetupAuditTest.php Replaces DryRemovalRuntimeEnvironment-based tests with direct RunTimeEnvironment calls; testComputeDryRemoval renamed and rewritten, but some previously covered paths remain untested.
tests/php-unit-tests/src/BaseTestCase/ItopTestCase.php Minor: adds a debug echo statement in tearDown that pollutes test output on every file-cleanup run.
setup/feature_removal/DryRemovalRuntimeEnvironment.php Deleted — its responsibilities have been absorbed into RunTimeEnvironment and the calling controller.
setup/itopextension.class.inc.php Adds HasCode() and HasLabel() helpers to iTopExtension; straightforward additions with no issues.
setup/sequencers/DataAuditSequencer.php Removes unused source_dir and extensions_dir parameters from the compile step; no functional impact.
tests/php-unit-tests/unitary-tests/setup/ExtensionsMapTest.php Adds four tests for CheckExtensionsValidity(); tests are well-structured and cover both the warning and exception paths.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant C as DataFeatureRemovalController
    participant RTE as RunTimeEnvironment
    participant EM as iTopExtensionsMap
    participant DC as DoCompile

    C->>EM: GetSelectedExtensions(config, added, removed)
    EM-->>C: aSelectedExtensions (indexed list of codes)
    C->>RTE: CopySetupFiles()
    C->>RTE: GetModulesToLoadFromChoices(config, aSelectedExtensions)
    RTE->>EM: GetScannedModulesRootDirs()
    RTE-->>C: aSelectedModules
    C->>DC: DoCompile(aSelectedExtensions, aRemovedExtensions, aSelectedModules)
    DC->>EM: GetExtensionsMap(buildEnv)
    DC->>EM: DeclareExtensionAsRemoved(aRemovedExtensionCodes)
    DC->>EM: CheckExtensionsValidity()
    DC-->>C: aSelectedModules
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant C as DataFeatureRemovalController
    participant RTE as RunTimeEnvironment
    participant EM as iTopExtensionsMap
    participant DC as DoCompile

    C->>EM: GetSelectedExtensions(config, added, removed)
    EM-->>C: aSelectedExtensions (indexed list of codes)
    C->>RTE: CopySetupFiles()
    C->>RTE: GetModulesToLoadFromChoices(config, aSelectedExtensions)
    RTE->>EM: GetScannedModulesRootDirs()
    RTE-->>C: aSelectedModules
    C->>DC: DoCompile(aSelectedExtensions, aRemovedExtensions, aSelectedModules)
    DC->>EM: GetExtensionsMap(buildEnv)
    DC->>EM: DeclareExtensionAsRemoved(aRemovedExtensionCodes)
    DC->>EM: CheckExtensionsValidity()
    DC-->>C: aSelectedModules
Loading

Reviews (4): Last reviewed commit: "N°9722 - ✅" | Re-trigger Greptile

Comment thread setup/extensionsmap.class.inc.php Outdated
Copilot AI review requested due to automatic review settings July 7, 2026 16:01
@eespie eespie closed this Jul 7, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Comment thread setup/runtimeenv.class.inc.php Outdated
Comment thread tests/php-unit-tests/unitary-tests/setup/feature_removal/SetupAuditTest.php Outdated
Comment thread tests/php-unit-tests/unitary-tests/setup/feature_removal/SetupAuditTest.php Outdated
@eespie eespie reopened this Jul 8, 2026
Copilot AI review requested due to automatic review settings July 8, 2026 09:45
@eespie eespie closed this Jul 8, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Comment thread setup/runtimeenv.class.inc.php Outdated
Comment thread tests/php-unit-tests/unitary-tests/setup/feature_removal/SetupAuditTest.php Outdated
@odain-cbd odain-cbd reopened this Jul 8, 2026
Copilot AI review requested due to automatic review settings July 8, 2026 14:32
@odain-cbd

Copy link
Copy Markdown
Contributor

@greptileai

Comment thread setup/runtimeenv.class.inc.php Outdated
@odain-cbd odain-cbd merged commit a3ef049 into develop Jul 8, 2026
@odain-cbd odain-cbd deleted the issue/9722-compil2 branch July 8, 2026 14:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 6 comments.

Comment on lines 193 to +194
foreach ($this->aFileToClean as $sPath) {
echo "aFileToClean: $sPath \n";
Comment thread setup/runtimeenv.class.inc.php Outdated
$this->InitExtensionMap($oConfig);
$aSelectedExtensions = $this->GetExtensionMap()->GetSelectedExtensions($oConfig, $aAddedExtensions, []);
$aSelectedModules = $this->GetModulesToLoadFromChoices($oConfig, $aSelectedExtensions);
return $this->DoCompile(array_keys($aSelectedExtensions), [], $aSelectedModules, $bUseSymLinks ?? false);
Comment on lines +199 to +202
//echo json_encode(array_keys($oExtensionMap->GetAllExtensions()), JSON_PRETTY_PRINT);

// $this->expectException(CoreException::class);
// $this->expectExceptionMessage("Selected extension(s) cannot be installed: Missing extension code ($sExtensionsDirAbsolute)");
Comment on lines +37 to +40
protected function tearDown(): void
{
parent::tearDown();
}
}
}

// For unit tests
Copilot AI review requested due to automatic review settings July 8, 2026 14:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 8 comments.

Comment on lines +73 to +77
$oConfig = new Config(utils::GetConfigFilePath($sSourceEnv));
$this->InitExtensionMap($oConfig);
$aSelectedExtensions = $this->GetExtensionMap()->GetSelectedExtensions($oConfig, $aAddedExtensions, []);
$aSelectedModules = $this->GetModulesToLoadFromChoices($oConfig, $aSelectedExtensions);
return $this->DoCompile(array_keys($aSelectedExtensions), [], $aSelectedModules, $bUseSymLinks ?? false);
Comment on lines 193 to 195
foreach ($this->aFileToClean as $sPath) {
echo "aFileToClean: $sPath \n";
if (is_file($sPath)) {
Comment on lines 1510 to 1514
$aExtensionDirs = [];
$aFromSelectedExtensionModules = [];
foreach ($this->GetExtensionMap()->GetAllExtensions() as $oExtension) {
if ($oExtension->IsMarkedAsChosen() && is_dir($oExtension->sSourceDir)) {
if (in_array($oExtension->sCode, $aChoices) && is_dir($oExtension->sSourceDir)) {
$aExtensionDirs [] = $oExtension->sSourceDir;
Comment on lines +5 to +13
use Combodo\iTop\DataFeatureRemoval\Service\DataFeatureRemoverExtensionService;
use Combodo\iTop\Test\UnitTest\ItopTestCase;
use Config;
use CoreException;
use DOMFormatException;
use Exception;
use iTopExtensionsMap;
use RunTimeEnvironment;
use utils;
Comment on lines +197 to +205
$oExtensionMap = ItopExtensionsMap::GetExtensionsMap($sEnvironment);

//echo json_encode(array_keys($oExtensionMap->GetAllExtensions()), JSON_PRETTY_PRINT);

// $this->expectException(CoreException::class);
// $this->expectExceptionMessage("Selected extension(s) cannot be installed: Missing extension code ($sExtensionsDirAbsolute)");

self::assertFalse($oExtensionMap->CheckExtensionsValidity(), 'Check extensions validity should have detected an extension without code.');
}
Comment on lines +224 to +232
$oExtensionMap = ItopExtensionsMap::GetExtensionsMap($sEnvironment);

//echo json_encode(array_keys($oExtensionMap->GetAllExtensions()), JSON_PRETTY_PRINT);

// $this->expectException(CoreException::class);
// $this->expectExceptionMessage("Selected extension(s) cannot be installed: Missing extension code ($sExtensionsDirAbsolute)");

self::assertFalse($oExtensionMap->CheckExtensionsValidity(), 'Check extensions validity should have detected an extension without code.');
}
Comment on lines +250 to +257
$oExtensionMap = ItopExtensionsMap::GetExtensionsMap($sEnvironment);
$oExtensionMap->MarkAsChosen('');

//echo json_encode(array_keys($oExtensionMap->GetAllExtensions()), JSON_PRETTY_PRINT);

$this->expectException(CoreException::class);
$this->expectExceptionMessage("Selected extension(s) cannot be installed: Missing extension code ($sExtensionsDirAbsolute)");

Comment on lines +278 to +285
$oExtensionMap = ItopExtensionsMap::GetExtensionsMap($sEnvironment);
$oExtensionMap->MarkAsChosen('');

//echo json_encode(array_keys($oExtensionMap->GetAllExtensions()), JSON_PRETTY_PRINT);

$this->expectException(CoreException::class);
$this->expectExceptionMessage("Selected extension(s) cannot be installed: Missing extension code (Broken extension)");

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

internal Work made by Combodo

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants