Proper way for gradle to run a never ending task? - gradle

I'm using gradle-node-plugin to help reduce dependencies for my project. Gradlew is basically replacing grunt or gulp in my project. This makes java my only dependency.
Before, I'd use npm run tsc and I had an npm task that would run tsc -w but now that npm is a gradle plugin, I can't call npm directly. I have the following task in my build.gradle:
task watch(dependsOn: 'npmInstall', type: NpmTask) {
outputs.upToDateWhen { false }
args = ['run', 'tsc']
}
Technically it works. It first makes sure that the npm plugin has installed all it's pieces (including typescript) and then will run my tsc task. The problem is that tsc -w never terminates. It watches my files for changes until I choose to terminate it. It does this successfully, but gradle constantly reports that the task is Building 75% > :watch. I have another task in package.json that offers up my files in an http-server and it behaves in the same way.
Is there a preferred way to have gradle run a never ending task like this or should I just let it think it's perpetually building?

Related

Passing arguments to a dependent task in gradle

When I run ./gradlew bootRun, I'd like for the npmInstall task that it depends on to run with the "--force" or "--legacy-peer-deps" arguments.
I tried using ./gradlew bootRun npm_install_--force but this doesn't make the npm install task that runs before the bootRun task use the --force argument. How can I pass either one of these arguments to the npmInstall task?
I'm running on windows and I need either one of these arguments so that I can resolve angular dependency issues. The npm version is 8.19.2
You should be able to create an .npmrc file with the following contents to solve this:
legacy-peer-deps=true

Gradle Wrapper not responding to commands

On my Linux machine in my root project directory I have the Gradle Wrapper
Project
|
+ src
|
+ gradlew
and when I run any command with gradlew there is no output, like for example when I print the version, there is no version printed
./gradlew --version
or when I check tasks, no tasks are displayed
./gradlew --tasks
or when I try to build the project, no out/ directory is created
./gradlew deploy
but when I click
Build > Build Project
in my Intellij IDE, the project does build, just not when I try to use Gradle from the command line.
So I have no idea what's going on with my gradle wrapper. Am I using the wrapper incorrectly?
My gradle wrapper which is just a Bash script, was empty ... somehow it's contents were deleted, so the script was running and nothing was happening. Good times.
It happened to me as well, the script was totally empty. The fix for me was to go to the gradle tab in IntelliJ and click on "Wrapper" under "Build setup".
After this my gradlew script got properly initialized.

Run a gulp watch simultaneously than gretty

I'm trying to run a gulp watch when running my Java web-app with Gretty.
I'm using this plugin to run gulp from Gradle.
For the moment, I'm just able to run a single gulp build before the app run by doing this: appRun.dependsOn gulp_build
What I would like is that when I run the app, there is also gulp watch starting (task gulp_default in Gradle on my case), so that SCSS files are automatically compiled when I save them without having to restart the app.
I can't just do appRun.dependsOn gulp_build because gulp_default doesn't return anything, so the gradle task doesn't execute appRun.
Any idea how I can do this?
I found a way, but by using npm to start the app and not gradle.
I used the concurrently package. I start the app by doing npm start instead of gradle appRun, and I added this in my package.json:
"scripts": {
"start": "concurrently \"gradle appRun\" \"gulp watch\""
}

Conditionally ordering tasks in Gradle

Consider a Gradle plugin that adds three tasks to a project - a buildZip task to create a distributable zip of the project, a publishZip task to publish that zip to a shared repository, and a cleanZip task to clean up any local version of the zip. For local development, cleanZip buildZip will be used frequently, but the automated build system will be running buildZip publishZip cleanZip.
One of the projects in which this plugin is being used wants to run their build using Gradle's parallel flag to allow the different parts of the project to be built in parallel. Unfortunately, this runs into a problem with the zip tasks - buildZip depends on the project actually building, but cleanZip doesn't have any dependencies so it can run right away, leading to the automated build system not being able to clean up.
Declaring any dependencies between these tasks isn't a good idea because they should be able to be run separately. Also, I can't specify mustRunAfter (at least between buildZip and cleanZip) because sometimes clean should be first and sometimes build should be first.
How can I tell Gradle what order to run these tasks in, in a way that will be honored by --parallel and isn't hardcoded to have a particular one always run before the other?
What you can do is: detect if gradle is run with --parallel and based on this configure dependencies between tasks appropriately. It can be done in the following way:
println project.gradle.startParameter.parallelProjectExecutionEnabled

Cancel Build if Task Runner Explorer Task Fails

I am using visual studio task runner (2015) to run a Gulp task bound to before build.
I have set it up so that when the gulp tasks fails it sends exit code 1 and at the end it says "Process terminated with code 1." however the build continues.
This will cancel the build in team city so seems an issue linked Task Runner inside visual studio.
How can I prevent the build from taking place if it exits with a code other than 0?
You are correct in that this seems to be a Task Runner issue. The task runner does not communicate with MSBuild to stop a build if a BeforeBuild task fails.
To get around this, you can run your Gulp task via the project's pre-build event instead of via the Task Runner bindings.
Set the pre-build event
For class libraries, you can access Build Events by right-clicking your project and selecting Properties -> Compile -> Build Events....
For web projects, they are located at Properties -> Build Events.
Here is the command I used to call the Gulp task in pre-build event, which will prevent the MSBuild from running if it exits with a failure:
gulp -b $(ProjectDir) --gulpfile $(ProjectDir)gulpfile.js my-task
This command calls Gulp passing absolute paths for working directory and gulpfile.js.
Notes:
I found all kinds of context and working directory issues trying to use a more straight up command like gulp my-task.
$(ProjectDir) is one of the Macros for Build Commands.
It is assumed that Gulp is installed globally: npm install -g gulp. See jonas.ninja's answer for how to build this install into the command (or for an alternative that does not require the global dependency).
I implemented davidmdem's solution above and it was great... on my system. I had gulp installed globally, but one of my coworkers did not, so the pre-build event would fail. Running gulp from Task Runner Explorer uses the project-level gulp installation, but running gulp from the pre-build script uses the global gulp installation.
To prevent the situation where a new developer doesn't have gulp installed, I expanded davidmdem's pre-build script to the following:
(gulp --version || npm install -g gulp#3.9.0) & gulp -b $(ProjectDir) --gulpfile $(ProjectDir)gulpfile.js my-task
This command installs gulp (version 3.9.0 to match the project-level gulp installation) only if it is not already installed. Now gulp is not something that you have to think about before you can build the project!
(Update:)
An alternative (in my opinion: better) solution to this problem is to use npm as an intermediary. Continuing and modifying from the example above, I have a gulp task my-task that is being called from the command line. This removed the global gulp dependency and still properly stops msbuild if gulp fails.
Pre-build event:
npm run build
package.json:
"scripts": {
"build": "gulp min"
}
I have build fail for jshint with gulp working (well enough for me, maybe sufficient for others.) I imagine it may be extended to include all the tasks in Task Runner.
Here is what I used/did...
As per this page, I added/edited this in my project.json, which hooks into the prebuild event...
"scripts": {
"prebuild": [ "gulp default" ]
}
As per this page, I included the following for my jshint task...
// =============================
// jsHint - error detection
// =============================
gulp.task("jshint", function () {
var jshGlobals = [
'$',
'jQuery',
'window',
'document',
'Element',
'Node',
'console'
];
gulp.src([paths.jsFiles, norefs])
.pipe(jshint({
predef: jshGlobals,
undef: true,
eqnull: true
}))
.pipe(jshint.reporter('jshint-stylish'))
.pipe(jshint.reporter('fail'))
});
The latter two lines being the most significant. You will need to npm install jshint-stylish if you don't already have it.
Alternatively, for jshint-stylish, you can let VS handle it for you. Add the line for jshint-stylish as indicated below to your package.json...
{
"name": "ASP.NET",
"version": "0.0.0",
"devDependencies": {
"es6-promise": "~3.1.2",
"gulp": "^3.8.11",
"del": "^2.2.0",
"jshint": "~2.9.1",
"jshint-stylish": "~2.1.0",
"gulp-jshint": "~2.0.0",
"gulp-flatten": "~0.2.0",
"gulp-rename": "~1.2.2",
"gulp-cssmin": "0.1.7",
"gulp-uglify": "1.2.0",
"gulp-postcss": "~6.1.0",
"autoprefixer": "~6.3.3"
}
}
Which gives me this when there is an error (in addition to the failed build) which is sufficient for me to dig further if/as necessary...
As opposed to the more detailed error info I get when running the same task via command line or Task Runner...
I imagine this solution can be improved but figured I would share as I hadn't seen a whole lot about it elsewhere.
Cheers.

Resources