Fail a grunt build when debug prints exist in source - gruntjs

I am working on a PHP/Javascript project where I've nicely set up a build workflow. It involves testing, minifying, compressing into the final zip deliverable, and a whole lot of other nice stuff.
I want to build a task that fails when there are certain patterns in the source code. I would like to look for any print_r(), error_log(), var_dump(), etc functions, and halt the build process if there are any. Perhaps later I would like to check for things in Javascript or CSS so this is not only a PHP question.
I know it can be done with grunt-shell and grep but I'd like to know the following:
Are there any grunt plugins specific to this task? Ideally I would like to be able to specify a list of regexes per file type, and to set whether to continue or fail the build on pattern match.
How do others tackle the problem of double-checking the packaged source for the most common debug statements or other patterns?

Not a complete answer to my question, but I've recently come across this grunt plugin which is somewhat related. It removes console.log statements from JavaScript. Haven't tried it yet. Looks good. I still would like to know if there's something similar for PHP though.
http://grunt-tasks.com/grunt-remove-logging-calls/
Edit: Seeing as there's only tumbleweeds rolling in the wind here, I'm posting my workaround that's based on grunt-shell. However this is not what I was looking for. It's not perfect because it doesn't do proper syntax parsing:
shell: {
check_debug_prints: {
command: '(! (egrep -r "var_dump|print_r|error_log" --include=*.php src || egrep -r "console\.\w+|debugger;" --include=*.js src) ) || (echo "Debug prints in source - build aborted" && false )'
}
},
and
grunt.loadNpmTasks( 'grunt-shell' );
Edit 2: I finally found the exact grunt plugin I was looking for. It is grunt-search. There is a failOnMatch boolean option that lets you indicate if a particular regex pattern should cause the build to fail when found.

Related

GNU make: include file only if target is not "clean"

Using GNU make, I want to include a file, except if the current target is "clean".
That is, I want to do the equivalent of the following:
ifneq($(TARGET),clean)
-include somefile.txt
endif
But for that, I need a variable whose value is the target given on the command line (here named $(TARGET)). Such a variable does not seem to exist, and I can understand why, because you could have multiple targets on the command line, some of which you might want to include the file for, and others not. Actually, it would be fine if the file is included when there are other targets besides "clean". The only real problem I currently have is that when the file to be included does not exist, Make will try to build it, which is unnecessary when you're about to delete it again when executing the "clean" target.
So, is there another way to accomplish what I want?
You can use MAKECMDGOALS. Use it like this to handle multiple arguments on the command line:
ifeq (clean,$(filter clean,$(MAKECMDGOALS)))
-include somefile.txt
endif
However, this is often fraught because if you run make clean all or whatever, the include file won't be included even though it might be needed for all.
If you really need this to be reliable another way is to use recursion for your "top-level" arguments, running them one at a time in a sub-make.
You could usefully check that if clean is a target then it is the only target. Otherwise strange things can go wrong silently causing much wailing and gnashing of teeth. My most recent Makefile includes the following. (NB tested but not as yet used extensively).
ifeq (clean,$(filter clean,$(MAKECMDGOALS)))
ifneq($(strip $(filter-out clean,$(MAKECMDGOALS)))
$(error ERROR: can not make other targets with clean
endif
endif

Error in system(command, intern = TRUE) : '“C:\Program' not found selectWeka function

I'm trying to run the code below from BioSeqClass package, however I get an error message:
Error in system(command, intern = TRUE) : '“C:\Program' not found
selectWeka(data, evaluator="CfsSubsetEval", search="BestFirst", n)
This is a problem with how BioSeqClass is calling java: it is leaving the file names unprotected/unquoted, and R's system and system2 commands are horrible by not forcing quoting. (If you ever think of using these commands directly yourself, I strongly recommend something like processx.)
One should create an issue or bug-report, but I don't know how to do that with Bioconductor, and their mirror on github (https://github.com/Bioconductor-mirror) is defunct, so I'm at a loss there. Hopefully somebody with more info can weigh in on this.
Workarounds
It is not obvious if the problem is due to where weka.jar is located or perhaps one of the other arguments. You can find out where the problem is by debugging the selectWeka function and inspecting the value of command before the system call. Look for the Program Files component of a path.
If the problem is with weka.jar, then this suggests that you are installing packages somewhere under C:\Program Files\, which is in my experience bad practice on two counts:
For many problems I cannot recall (but this one re-ignites the discussion), I never install R in the default location under C:\Program Files\...; instead, I install it under a new directory, C:\R\R-3.5.3 (version-based) and go from there. You may not have control over this if on a university/company system.
Since this is not in a base-R package, this suggests that either you are not using a personal library location (collection of packages), or have placed your personal library for some reason under C:\Program Files. If the former, I strongly suggest you never install new packages inside the base-R installation directory, instead using your own. See ?.libPaths and many other tutorials/discussions on the topic online. Using packrat or checkpoint might also mitigate this problem.
If the problem is with trainFile (if I'm reading the source correctly), then your "permanent" fix is to change where Windows puts temporary files, as this trainFile is a temporary file created specifically for this function-run. If this is your problem, I'll leave it up to you to fix.
Regardless, you may not have time or need to make a more permanent solution, you just want to run this once or twice and then move on. For that fix:
Again, debug(selectWeka), and once command is defined (the next command to be executed is tmp <- system(command,intern = TRUE)), run this code to fix the value of command:
if(search=="Ranker"){
command = paste("java -cp ", shQuote(file.path(.path.package("BioSeqClass"), "scripts", "weka.jar")),
" weka.attributeSelection.", evaluator, " -i ", shQuote(trainFile),
" -s \"weka.attributeSelection.", search, " -N ", n, "\"", sep="" )
}else{
command = paste("java -cp ", shQuote(file.path(.path.package("BioSeqClass"), "scripts", "weka.jar")),
" weka.attributeSelection.", evaluator, " -i ", shQuote(trainFile),
" -s weka.attributeSelection.", search, sep="" )
}
(For the record, all I changed was adding shQuote twice to each paste.) Confirm that command now has quotes around things, something like
Browse[2]> command
[1] "java -cp \"C:\\Program Files\\...\\weka.jar" weka.attributeSel... -i \"c:\\path\\to\\some\\tempfile\" ...
Then you can continue-out of the debugger and let it run its course.
(I hope you don't have hundreds of calls to selectWeka.)
Caveat: I am not a use of BioSeqClass, so I'm saying all of this from speculation and inference. I might have mis-located the source of the error. And since I don't know what I'm doing with it, I have not tested the modified command assignment within selectWeka. I believe shQuote(...) is the right way to go, but you might need to use sQuote or dQuote instead, I'm not sure how your system is setup.

How to combine two Vim commands into one (command not keybinding)

I've found few Stack Overflow questions talking about this, but they are all regarding only the :nmap or :noremap commands.
I want a command, not just a keybinding. Is there any way to accomplish this?
Use-case:
When I run :make, I doesn't saves automatically. So I'd like to combine :make and :w. I'd like to create a command :Compile/:C or :Wmake to achieve this.
The general information about concatenating Ex command via | can be found at :help cmdline-lines.
You can apply this for interactive commands, in mappings, and in custom commands as well.
Note that you only need to use the special <bar> in mappings (to avoid to prematurely conclude the mapping definition and execute the remainder immediately, a frequent beginner's mistake: :nnoremap <F1> :write | echo "This causes an error during Vim startup!"<CR>). For custom commands, you can just write |, but keep in mind which commands see this as their argument themselves.
:help line-continuation will help with overly long command definitions. Moving multiple commands into a separate :help :function can help, too (but note that this subtly changes the error handling).
arguments
If you want to pass custom command-line arguments, you can add -nargs=* to your :command definition and then specify the insertion point on the right-hand side via <args>. For example, to allow commands to your :write command, you could use
:command -nargs=* C w <args> | silent make | redraw!
You can combine commands with |, see help for :bar:
command! C update | silent make | redraw!
However, there is a cleaner way to achieve what you want.
Just enable the 'autowrite' option to automatically write
modified files before a :make:
'autowrite' 'aw' 'noautowrite' 'noaw'
'autowrite' 'aw' boolean (default off)
global
Write the contents of the file, if it has been modified, on each
:next, :rewind, :last, :first, :previous, :stop, :suspend, :tag, :!,
:make, CTRL-] and CTRL-^ command; and when a :buffer, CTRL-O, CTRL-I,
'{A-Z0-9}, or `{A-Z0-9} command takes one to another file.
Note that for some commands the 'autowrite' option is not used, see
'autowriteall' for that.
This option is mentioned in the help for :make.
I have found a solution after a bit of trial and error.
Solution for my usecase
command C w <bar> silent make <bar> redraw!
This is for compiling using make and it prints output only if there is nonzero output.
General solution
command COMMAND_NAME COMMAND_TO_RUN
Where COMMAND_TO_RUN can be constructed using more than one command using the following construct.
COMMAND_1_THAN_2 = COMMAND_1 <bar> COMMAND_2
You can use this multiple times and It is very similar to pipes in shell.

Debugging bitbake pkg_postinst_${PN}: Append to config-file installed by other recipe

I'm writing am openembedded/bitbake recipe for openembedded-classic. My recipe RDEPENDS on keyutils, and everything seems to work, except one thing:
I want to append a single line to the /etc/request-key.conf file installed by the keyutils package. So I added the following to my recipe:
pkg_postinst_${PN} () {
echo 'create ... more stuff ..' >> ${sysconfdir}/request-key.conf
}
However, the intended added line is missing in my resulting image.
My recipe inherits update-rc.d if that makes any difference.
My main question is: How do i debug this? Currently I am constructing an entire rootfs image, and then poke-around in that to see, if the changes show up. Surely there is a better way?
UPDATE:
Changed recipe to:
pkg_postinst_${PN} () {
echo 'create ... more stuff ...' >> ${D}${sysconfdir}/request-key.conf
}
But still no luck.
As far as I know, postinst runs at rootfs creation, and only at first boot if rootfs fails.
So there is a easy way to execute something only first boot. Just check for $D, like this:
pkg_postinst_stuff() {
#!/bin/sh -e
if [ x"$D" = "x" ]; then
# do something at first boot here
else
exit 1
fi
}
postinst scripts are ran at roots time, so ${sysconfdir} is /etc on your host. Use $D${sysconfdir} to write to the file inside the rootfs being generated.
OE-Classic is pretty ancient so you really should update to oe-core.
That said, Do postinst's run at first boot? I'm not sure. Also look in the recipes work directory in the temp directory and read the log and run files to see if there are any clues there.
One more thing. If foo RDEPENDS on bar that just means "when foo is installed, bar is also installed". I'm not sure it makes assertions about what is installed during the install phase, when your postinst is running.
If using $D doesn't fix the problem try editing your postinst to copy the existing file you're trying to edit somewhere else, so you can verify that it exists in the first place. Its possible that you're appending to a file that doesn't exist yet, and the the package that installs the file replaces it.

Does sbt have something like gradle's processResources task with ReplaceTokens support?

We are moving into Scala/SBT from a Java/Gradle stack. Our gradle builds were leveraging a task called processResources and some Ant filter thing named ReplaceTokens to dynamically replace tokens in a checked-in .properties file without actually changing the .properties file (just changing the output). The gradle task looks like:
processResources {
def whoami = System.getProperty( 'user.name' );
def hostname = InetAddress.getLocalHost().getHostName()
def buildTimestamp = new Date().format('yyyy-MM-dd HH:mm:ss z')
filter ReplaceTokens, tokens: [
"buildsig.version" : project.version,
"buildsig.classifier" : project.classifier,
"buildsig.timestamp" : buildTimestamp,
"buildsig.user" : whoami,
"buildsig.system" : hostname,
"buildsig.tag" : buildTag
]
}
This task locates all the template files in the src/main/resources directory, performs the requisite substitutions and outputs the results at build/resources/main. In other words it transforms src/main/resources/buildsig.properties from...
buildsig.version=#buildsig.version#
buildsig.classifier=#buildsig.classifier#
buildsig.timestamp=#buildsig.timestamp#
buildsig.user=#buildsig.user#
buildsig.system=#buildsig.system#
buildsig.tag=#buildsig.tag#
...to build/resources/main/buildsig.properties...
buildsig.version=1.6.5
buildsig.classifier=RELEASE
buildsig.timestamp=2013-05-06 09:46:52 PDT
buildsig.user=jenkins
buildsig.system=bobk-mbp.local
buildsig.tag=dev
Which, ultimately, finds its way into the WAR file at WEB-INF/classes/buildsig.properties. This works like a champ to record build specific information in a Properties file which gets loaded from the classpath at runtime.
What do I do in SBT to get something like this done? I'm new to Scala / SBT so please forgive me if this seems a stupid question. At the end of the day what I need is a means of pulling some information from the environment on which I build and placing that information into a properties file that is classpath loadable at runtime. Any insights you can give to help me get this done are greatly appreciated.
The sbt-buildinfo is a good option. The README shows an example of how to define custom mappings and mappings that should run on each compile. In addition to the straightforward addition of normal settings like version shown there, you want a section like this:
buildInfoKeys ++= Seq[BuildInfoKey](
"hostname" -> java.net.InetAddress.getLocalHost().getHostName(),
"whoami" -> System.getProperty("user.name"),
BuildInfoKey.action("buildTimestamp") {
java.text.DateFormat.getDateTimeInstance.format(new java.util.Date())
}
)
Would the following be what you're looking for:
sbt-editsource: An SBT plugin for editing files
sbt-editsource is a text substitution plugin for SBT 0.11.x and
greater. In a way, it’s a poor man’s sed(1), for SBT. It provides the
ability to apply line-by-line substitutions to a source text file,
producing an edited output file. It supports two kinds of edits:
Variable substitution, where ${var} is replaced by a value. sed-like
regular expression substitution.
This is from Community Plugins.

Resources