Skip to content

Commit e334cf1

Browse files
author
Sten Roger Sandvik
committed
Fixed merge conflicts
2 parents 2dc1c34 + 00cc0c8 commit e334cf1

File tree

18 files changed

+535
-603
lines changed

18 files changed

+535
-603
lines changed

README.md

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,44 @@ the class `NpmTask`:
127127
args = ['install', 'express', '--save-dev']
128128
}
129129

130+
Executing Yarn Tasks
131+
---------------------
132+
133+
When adding the node plugin, you will have a yarn task already added. This
134+
task will execute `yarn` and installs all dependencies in `package.json`.
135+
It will only run when changes are made to `package.json`, `yarn.lock`, or `node_modules`.
136+
Execute it like this:
137+
138+
$ gradle yarn
139+
140+
All npm command can also be invoked using underscore notation based on a gradle
141+
rule:
142+
143+
$ gradle yarn_install
144+
$ gradle yarn_upgrade
145+
$ gradle yarn_ls
146+
$ gradle yarn_cache_clean
147+
...
148+
149+
These however are not shown when running gradle tasks, as they generated
150+
dynamically. However they can be used for dependency declarations, such as:
151+
152+
yarn_install.dependsOn(yarn_cache_clean)
153+
154+
More arguments can be passed via the build.gradle file:
155+
156+
yarn_cache_clean {
157+
args = ['--no-emoji', '--json']
158+
}
159+
160+
If you want to extend the tasks more or create custom variants, you can extend
161+
the class `YarnTask`:
162+
163+
task addExpress(type: YarnTask) {
164+
// add the express package only
165+
args = ['add', 'express', '--dev']
166+
}
167+
130168
Configuring the Plugin
131169
----------------------
132170

@@ -139,6 +177,9 @@ You can configure the plugin using the "node" extension block, like this:
139177
// Version of npm to use.
140178
npmVersion = '2.1.5'
141179

180+
// Version of Yarn to use.
181+
yarnVersion = '0.16.1'
182+
142183
// Base URL for fetching node distributions (change if you have a mirror).
143184
distBaseUrl = 'https://nodejs.org/dist'
144185

@@ -149,6 +190,12 @@ You can configure the plugin using the "node" extension block, like this:
149190
// Set the work directory for unpacking node
150191
workDir = file("${project.buildDir}/nodejs")
151192

193+
// Set the work directory for NPM
194+
npmWorkDir = file("${project.buildDir}/npm")
195+
196+
// Set the work directory for Yarn
197+
yarnWorkDir = file("${project.buildDir}/yarn")
198+
152199
// Set the work directory where node_modules should be located
153200
nodeModulesDir = file("${project.projectDir}")
154201
}
@@ -158,13 +205,24 @@ You can configure the plugin using the "node" extension block, like this:
158205
Using a Custom (project-local) Version of `npm`
159206
-----------------------------------------------
160207

161-
The plugin will use a locally-installed `npm` if it exists, regardless of the
162-
method of installation.
208+
If `npmVersion` is specified, the plugin installs that version of `npm` into `npmWorkDir`
209+
by the `npmSetup` task and use it.
210+
211+
If `npmVersion` is not specified and a locally-installed `npm` exists, The plugin will
212+
use it.
213+
214+
Otherwise, the plugin will use the `npm` bundled with the version of node installation.
215+
216+
Using a Custom (project-local) Version of `yarn`
217+
-----------------------------------------------
218+
219+
The plugin never uses a locally-installed `yarn` because it may be deleted during
220+
`yarn` execution.
221+
Instead, it installs `yarn` into `yarnWorkDir` (`.gradle/yarn/` by default) by
222+
the `yarnSetup` task and use it.
163223

164-
If you would like the plugin to install use a custom version of npm rather than
165-
the one bundled with the version of node installation, you can set `npmVersion`
166-
in the `node` extension block. The plugin will install the npm to the project's
167-
`node_modules` directory by configuring the `npmSetup` task.
224+
If you would like the plugin to install use a custom version of yarn, you can set
225+
`yarnVersion` in the `node` extension block.
168226

169227
Building the Plugin
170228
-------------------
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.moowork.gradle.node
2+
3+
import com.moowork.gradle.AbstractIntegTest
4+
5+
class YarnInstall_integTest
6+
extends AbstractIntegTest
7+
{
8+
def 'install packages with yarn'()
9+
{
10+
given:
11+
writeBuild( '''
12+
apply plugin: 'com.moowork.node'
13+
14+
node {
15+
version = "6.9.1"
16+
yarnVersion = "0.16.1"
17+
download = true
18+
workDir = file('build/node')
19+
yarnWorkDir = file('build/yarn')
20+
}
21+
''' )
22+
writeEmptyPackageJson()
23+
24+
when:
25+
def result = runTasksSuccessfully( 'yarn' )
26+
27+
then:
28+
result.wasExecuted( 'yarn' )
29+
30+
when:
31+
result = runTasksSuccessfully( 'yarn' )
32+
33+
then:
34+
result.wasUpToDate( 'yarn' )
35+
}
36+
37+
def 'install packages with yarn in different directory'()
38+
{
39+
given:
40+
writeBuild( '''
41+
apply plugin: 'com.moowork.node'
42+
43+
node {
44+
version = "6.9.1"
45+
yarnVersion = "0.15.1"
46+
download = true
47+
workDir = file('build/node')
48+
yarnWorkDir = file('build/yarn')
49+
nodeModulesDir = file('subdirectory')
50+
}
51+
''' )
52+
writeFile( 'subdirectory/package.json', """{
53+
"name": "example",
54+
"dependencies": {
55+
}
56+
}""" )
57+
58+
when:
59+
def result = runTasksSuccessfully( 'yarn' )
60+
61+
then:
62+
result.wasExecuted( 'yarn' )
63+
}
64+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package com.moowork.gradle.node
2+
3+
import com.moowork.gradle.AbstractIntegTest
4+
5+
class YarnRule_integTest
6+
extends AbstractIntegTest
7+
{
8+
def 'execute yarn_install rule'()
9+
{
10+
given:
11+
writeBuild( '''
12+
apply plugin: 'com.moowork.node'
13+
14+
node {
15+
version = "6.9.1"
16+
yarnVersion = "0.16.1"
17+
download = true
18+
workDir = file('build/node')
19+
yarnWorkDir = file('build/yarn')
20+
}
21+
''' )
22+
writeEmptyPackageJson()
23+
24+
when:
25+
def result = runTasksSuccessfully( 'yarn_install' )
26+
27+
then:
28+
result.wasExecuted( 'yarn_install' )
29+
}
30+
31+
def 'can execute an yarn module using yarn_run_'()
32+
{
33+
given:
34+
writeBuild( '''
35+
apply plugin: 'com.moowork.node'
36+
37+
node {
38+
version = "6.9.1"
39+
yarnVersion = "0.17.5"
40+
download = true
41+
}
42+
''' )
43+
44+
copyResources( 'fixtures/yarn/package.json', 'package.json' )
45+
46+
when:
47+
def result = runTasksSuccessfully( 'yarn_run_parent' )
48+
49+
then:
50+
result.success
51+
fileExists( 'child1.txt' )
52+
fileExists( 'child2.txt' )
53+
fileExists( 'parent1.txt' )
54+
fileExists( 'parent2.txt' )
55+
}
56+
57+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "example",
3+
"devDependencies": {
4+
"yarn": "0.16.1",
5+
"concurrently": "3.1.0"
6+
},
7+
"dependencies": {
8+
"less": "2.6.1"
9+
},
10+
"scripts": {
11+
"child1": "echo \"child1\" > child1.txt",
12+
"child2": "echo \"child2\" > child2.txt",
13+
"parent": "echo \"parent1\" > parent1.txt && concurrently \"yarn run child1\" \"yarn run child2\" && echo \"parent2\" > parent2.txt"
14+
}
15+
}

src/main/groovy/com/moowork/gradle/node/NodeExtension.groovy

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,24 @@ class NodeExtension
99

1010
def File workDir
1111

12+
def File npmWorkDir
13+
14+
def File yarnWorkDir
15+
1216
def File nodeModulesDir
1317

1418
def String version = '4.4.0'
1519

1620
def String npmVersion = ''
1721

22+
def String yarnVersion = ''
23+
1824
def String distBaseUrl = 'https://nodejs.org/dist'
1925

2026
def String npmCommand = 'npm'
2127

28+
def String yarnCommand = 'yarn'
29+
2230
def boolean download = false
2331

2432
def Variant variant
@@ -27,6 +35,8 @@ class NodeExtension
2735
{
2836
def cacheDir = new File( project.projectDir, '.gradle' )
2937
this.workDir = new File( cacheDir, 'nodejs' )
38+
this.npmWorkDir = new File( cacheDir, 'npm' )
39+
this.yarnWorkDir = new File( cacheDir, 'yarn' )
3040
this.nodeModulesDir = project.projectDir
3141
}
3242

src/main/groovy/com/moowork/gradle/node/NodePlugin.groovy

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ class NodePlugin
1616

1717
private NpmSetupTask npmSetupTask
1818

19+
private YarnSetupTask yarnSetupTask
20+
1921
@Override
2022
void apply( final Project project )
2123
{
@@ -25,25 +27,30 @@ class NodePlugin
2527
addGlobalTypes()
2628
addTasks()
2729
addNpmRule()
30+
addYarnRule()
2831

2932
this.project.afterEvaluate {
3033
this.config.variant = new VariantBuilder( this.config ).build()
3134
configureSetupTask()
3235
configureNpmSetupTask()
36+
configureYarnSetupTask()
3337
}
3438
}
3539

3640
private void addGlobalTypes()
3741
{
3842
addGlobalTaskType( NodeTask )
3943
addGlobalTaskType( NpmTask )
44+
addGlobalTaskType( YarnTask )
4045
}
4146

4247
private void addTasks()
4348
{
4449
this.project.tasks.create( NpmInstallTask.NAME, NpmInstallTask )
50+
this.project.tasks.create( YarnInstallTask.NAME, YarnInstallTask )
4551
this.setupTask = this.project.tasks.create( SetupTask.NAME, SetupTask )
4652
this.npmSetupTask = this.project.tasks.create( NpmSetupTask.NAME, NpmSetupTask )
53+
this.yarnSetupTask = this.project.tasks.create( YarnSetupTask.NAME, YarnSetupTask )
4754
}
4855

4956
private void addGlobalTaskType( Class type )
@@ -70,6 +77,25 @@ class NodePlugin
7077
}
7178
}
7279

80+
private void addYarnRule()
81+
{
82+
// note this rule also makes it possible to specify e.g. "dependsOn yarn_install"
83+
project.getTasks().addRule( 'Pattern: "yarn_<command>": Executes an Yarn command.' ) { String taskName ->
84+
if ( taskName.startsWith( "yarn_" ) )
85+
{
86+
YarnTask yarnTask = project.getTasks().create( taskName, YarnTask.class )
87+
String[] tokens = taskName.split( '_' ).tail() // all except first
88+
yarnTask.yarnCommand = tokens
89+
90+
if (tokens.head().equalsIgnoreCase("run")) {
91+
yarnTask.dependsOn(YarnInstallTask.NAME)
92+
}
93+
94+
return yarnTask
95+
}
96+
}
97+
}
98+
7399
private void configureSetupTask()
74100
{
75101
this.setupTask.setEnabled( this.config.download )
@@ -79,4 +105,9 @@ class NodePlugin
79105
{
80106
this.npmSetupTask.configureNpmVersion( this.config.npmVersion )
81107
}
108+
109+
private void configureYarnSetupTask()
110+
{
111+
this.yarnSetupTask.configureYarnVersion( this.config.yarnVersion )
112+
}
82113
}

src/main/groovy/com/moowork/gradle/node/exec/NpmExecRunner.groovy

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,16 @@ class NpmExecRunner
2626

2727
def String npmScriptFile = this.variant.npmScriptFile
2828
def File localNpm = project.file( new File( this.ext.nodeModulesDir, 'node_modules/npm/bin/npm-cli.js' ) )
29+
def File workNpm = project.file( new File( this.ext.npmWorkDir, 'node_modules/npm/bin/npm-cli.js' ) )
2930

30-
// Use locally-installed npm if available
31-
if ( localNpm.exists() )
31+
// Use npm specified by user if available
32+
if ( workNpm.exists() )
3233
{
33-
npmScriptFile = localNpm.absolutePath
34+
npmScriptFile = workNpm.absolutePath
3435
}
35-
36-
boolean notInstalling = !arguments.join(' ').startsWith('install')
37-
boolean configuredLocalNpm = !project.node.npmVersion.empty
38-
39-
if ( !localNpm.exists() && configuredLocalNpm && notInstalling )
40-
{
41-
throw new InvalidUserDataException("""
42-
Could not run npm command - local npm not found but requested in gradle node configuration.
43-
A common reason for this is an npm-shrinkwrap.json file is present and un-installs npm.
44-
To resolve this, add npm with version '${project.node.npmVersion}' to your package.json.
45-
""".stripIndent())
36+
// Use locally-installed npm if available
37+
else if ( localNpm.exists() ) {
38+
npmScriptFile = localNpm.absolutePath
4639
}
4740

4841
def runner = new NodeExecRunner( this.project )

0 commit comments

Comments
 (0)