Skip to content

Commit

Permalink
Use .nvmrc for picking the right version of Node.js.
Browse files Browse the repository at this point in the history
Since Moodle 3.5 there is .nvmrc file at the top directory specifying
Node.js (npm) version Node Package Manager (nvm) should install.

We can use this to initialise Node.js environment as part of install
process, so that user would not need to worry about having correct
version of Node in before_install step.

This closes #7
  • Loading branch information
kabalin committed Jul 19, 2020
1 parent 9f98b64 commit 654767f
Show file tree
Hide file tree
Showing 14 changed files with 178 additions and 33 deletions.
2 changes: 0 additions & 2 deletions .travis.dist.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ env:

before_install:
- phpenv config-rm xdebug.ini
- nvm install 14.0.0
- nvm use 14.0.0
- cd ../..
- composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^2
- export PATH="$(cd ci/bin; pwd):$(cd ci/vendor/bin; pwd):$PATH"
Expand Down
4 changes: 1 addition & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,14 @@ env:

before_install:
- phpenv config-rm xdebug.ini
- nvm install 14.0.0
- nvm use 14.0.0
- make init
# Mimic how a Moodle plugin would be run.
- cp -R tests/Fixture/moodle-local_travis ../moodle-local_travis
- export PATH="$(cd bin; pwd):$(cd vendor/bin; pwd):$PATH"
- export TRAVIS_BUILD_DIR=$(cd ../moodle-local_travis; pwd)

install:
- moodle-plugin-ci install
- moodle-plugin-ci install -vvv

script:
- make test-phpunit
Expand Down
6 changes: 5 additions & 1 deletion docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ The format of this change log follows the advice given at [Keep a CHANGELOG](htt
this is no longer required, you can remove this step.
- Updated version of `moodlehq/moodle-local_codechecker` to v2.9.6
- Updated [.travis.dist.yml] to build Moodle 3.9
- Updated [.travis.dist.yml] to use nvm 14.0.0
- `moodle-plugin-ci install` installs Node.js (npm) using the version
specified in .nvmrc file. See
[#7](https://github.com/moodlehq/moodle-plugin-ci/issues/7)
- ACTION REQUIRED: You may safely remove `nvm install <version>` and `nvm use
<version>` from .travis.yml for Moodle 3.5 and above, this is now a part of installation routine.

### Added
- New help document: [CLI commands and options](CLI.md)
Expand Down
4 changes: 0 additions & 4 deletions docs/TravisFileExplained.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,6 @@ env:
before_install:
# This disables XDebug which should speed up the build.
- phpenv config-rm xdebug.ini
# This installs NodeJS which is used by Grunt, adjust according to `.nvmrc` file
# in your Moodle installation.
- nvm install 14.0.0
- nvm use 14.0.0
# Currently we are inside of the clone of your repository. We move up two
# directories to build the project.
- cd ../..
Expand Down
7 changes: 7 additions & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@
</errorLevel>
</PossiblyNullReference>

<!-- Psalm complains that getenv output can't be concatenated -->
<PossiblyFalseOperand>
<errorLevel type="suppress">
<file name="src/Process/Execute.php"/>
</errorLevel>
</PossiblyFalseOperand>

<!-- Psalm is not finding inherited PHPDoc -->
<MissingReturnType>
<errorLevel type="suppress">
Expand Down
1 change: 1 addition & 0 deletions src/Installer/TestSuiteInstaller.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ public function getBehatInstallProcesses()
return [];
}

// @see BehatCommand::execute()
$this->addEnv('MOODLE_START_BEHAT_SERVERS', 'YES');

return [
Expand Down
34 changes: 33 additions & 1 deletion src/Installer/VendorInstaller.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,27 @@ public function __construct(Moodle $moodle, MoodlePlugin $plugin, Execute $execu

public function install()
{
// If .nvmrc exists, use it to initialise the right version of Node.js.
if ($this->canInstallNode()) {
$this->getOutput()->step('Installing Node.js version specified in .nvmrc');
$nvmDir = getenv('NVM_DIR');
$cmd = ". $nvmDir/nvm.sh && nvm install && nvm use && echo \"NVM_BIN=\$NVM_BIN\"";
$process = $this->execute->passThrough($cmd, $this->moodle->directory);
if (!$process->isSuccessful()) {
throw new \RuntimeException('Node.js installation failed.');
}
// Retrieve NVM_BIN from initialisation output, we will use it to
// substitute right Node.js environment in all future process runs.
// @see Execute::setNodeEnv()
preg_match('/^NVM_BIN=(.+)$/m', trim($process->getOutput()), $matches);
if (isset($matches[1]) && is_dir($matches[1])) {
$this->addEnv('RUNTIME_NVM_BIN', $matches[1]);
putenv('RUNTIME_NVM_BIN='.$matches[1]);
} else {
$this->getOutput()->debug('Can\'t retrieve NVM_BIN content from the command output.');
}
}

$this->getOutput()->step('Install global dependencies');

$processes = [];
Expand All @@ -68,6 +89,17 @@ public function install()

public function stepCount()
{
return 2;
return ($this->canInstallNode()) ? 3 : 2;
}

/**
* Check if we have everything needed to proceed with Node.js installation step.
*
* @return bool
*/
private function canInstallNode()
{
// TODO: Check if currently installed Node.js is matching.
return is_file($this->moodle->directory.'/.nvmrc') && getenv('NVM_DIR');
}
}
44 changes: 42 additions & 2 deletions src/Process/Execute.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,36 @@ public function __construct(OutputInterface $output, ProcessHelper $helper)
$this->helper = $helper;
}

/**
* Sets Node.js environment for process.
*
* We call 'nvm use' as part of install routine, but we can't export env
* variable containing path to required version npm binary to make it
* available in each script run (CI step). To overcome that limitation,
* we store this path in RUNTIME_NVM_BIN custom variable (that install step
* dumps into .env file) and use it to substitute Node.js environment
* in processes we execute.
*
* @param Process $process An instance of Process
*
* @return Process
*/
public function setNodeEnv(Process $process)
{
if (getenv('RUNTIME_NVM_BIN')) {
// Concatinate RUNTIME_NVM_BIN with PATH, so the correct version of
// npm binary is used within process.
$env = ['PATH' => getenv('RUNTIME_NVM_BIN').':'.getenv('PATH')];
$process->setEnv($env);
// Make sure we have all system env vars available too.
// TODO: Env vars are inherited by default in Symfony 4, next line
// can be removed after upgrade.
$process->inheritEnvironmentVariables(true);
}

return $process;
}

/**
* @param string|array|Process $cmd An instance of Process or an array of arguments to escape and run or a command to run
* @param string|null $error An error message that must be displayed if something went wrong
Expand All @@ -55,6 +85,11 @@ public function __construct(OutputInterface $output, ProcessHelper $helper)
*/
public function run($cmd, $error = null)
{
if (!($cmd instanceof Process)) {
$cmd = new Process($cmd);
}
$this->setNodeEnv($cmd);

return $this->helper->run($this->output, $cmd, $error);
}

Expand All @@ -66,6 +101,11 @@ public function run($cmd, $error = null)
*/
public function mustRun($cmd, $error = null)
{
if (!($cmd instanceof Process)) {
$cmd = new Process($cmd);
}
$this->setNodeEnv($cmd);

return $this->helper->mustRun($this->output, $cmd, $error);
}

Expand All @@ -81,7 +121,7 @@ public function runAll($processes)
return;
}
foreach ($processes as $process) {
$process->start();
$this->setNodeEnv($process)->start();
usleep($this->parallelWaitTime);
}
foreach ($processes as $process) {
Expand Down Expand Up @@ -132,7 +172,7 @@ public function passThroughProcess(Process $process)
if ($this->output->isVeryVerbose()) {
$this->output->writeln(sprintf('<bg=blue;fg=white;> RUN </> <fg=blue>%s</>', $process->getCommandLine()));
}
$process->run(function ($type, $buffer) {
$this->setNodeEnv($process)->run(function ($type, $buffer) {
$this->output->write($buffer);
});

Expand Down
2 changes: 1 addition & 1 deletion tests/Bridge/MoodleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ class MoodleTest extends \PHPUnit_Framework_TestCase
public function testGetBranch()
{
$moodle = new Moodle(__DIR__.'/../Fixture/moodle');
$this->assertSame(29, $moodle->getBranch());
$this->assertSame(39, $moodle->getBranch());
}
}
1 change: 1 addition & 0 deletions tests/Fixture/moodle/.nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v14.0.0
8 changes: 3 additions & 5 deletions tests/Fixture/moodle/version.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,9 @@

defined('MOODLE_INTERNAL') || die();

$version = 2015051103.00; // 20150511 = branching date YYYYMMDD - do not modify!
$version = 2020061500.00; // 20200615 = branching date YYYYMMDD - do not modify!
// RR = release increments - 00 in DEV branches.
// .XX = incremental changes.

$release = '2.9.3 (Build: 20151109)'; // Human-friendly version name

$branch = '29'; // This version's branch.
$release = '3.9 (Build: 20200615)'; // Human-friendly version name
$branch = '39'; // This version's branch.
$maturity = MATURITY_STABLE; // This version's maturity level.
8 changes: 4 additions & 4 deletions tests/Installer/MoodleInstallerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,21 @@
use MoodlePluginCI\Installer\MoodleInstaller;
use MoodlePluginCI\Tests\Fake\Bridge\DummyMoodle;
use MoodlePluginCI\Tests\Fake\Process\DummyExecute;
use MoodlePluginCI\Tests\FilesystemTestCase;
use MoodlePluginCI\Tests\MoodleTestCase;

class MoodleInstallerTest extends FilesystemTestCase
class MoodleInstallerTest extends MoodleTestCase
{
public function testInstall()
{
$dataDir = $this->tempDir.'/moodledata';
$moodle = new DummyMoodle($this->tempDir);
$moodle = new DummyMoodle($this->moodleDir);
$installer = new MoodleInstaller(
new DummyExecute(),
new MySQLDatabase(),
$moodle,
new MoodleConfig(),
'[email protected]:moodle/moodle.git',
'MOODLE_27_STABLE',
'MOODLE_39_STABLE',
$dataDir
);
$installer->install();
Expand Down
22 changes: 19 additions & 3 deletions tests/Installer/VendorInstallerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,34 @@
use MoodlePluginCI\Installer\VendorInstaller;
use MoodlePluginCI\Tests\Fake\Bridge\DummyMoodle;
use MoodlePluginCI\Tests\Fake\Process\DummyExecute;
use MoodlePluginCI\Tests\MoodleTestCase;

class VendorInstallerTest extends \PHPUnit_Framework_TestCase
class VendorInstallerTest extends MoodleTestCase
{
public function testInstall()
{
$installer = new VendorInstaller(
new DummyMoodle(''),
new MoodlePlugin(__DIR__.'/../Fixture/moodle-local_travis'),
new DummyMoodle($this->moodleDir),
new MoodlePlugin($this->pluginDir),
new DummyExecute()
);
$installer->install();

$this->assertSame($installer->stepCount(), $installer->getOutput()->getStepCount());
}

public function testCanInstallNode()
{
$installer = new VendorInstaller(
new DummyMoodle($this->moodleDir),
new MoodlePlugin($this->pluginDir),
new DummyExecute()
);

$this->assertTrue($installer->canInstallNode());

$this->fs->remove($this->moodleDir.'/.nvmrc');

$this->assertFalse($installer->canInstallNode());
}
}
Loading

0 comments on commit 654767f

Please sign in to comment.