Can I use sbt to build my own stand-alone console? - scala

I really like sbt and its extendibility. I'd like to use it as the basis of my own little stand-alone console-like tool. Basically it would have a bunch of tasks and such. I'm thinking something like Lifty, but I'd like to have one command that would launch sbt, load any relevant plugins (whether Lifty or my own), and then present users with my own custom prompt with a limited set of tasks & settings available.
Is this possible without jumping through a lot of hoops?

Yes, it is, and stuff like Play and Akka do exactly that. You might get an inkling on how to do all you need with sbt-extras, or looking at the above-mentioned projects.

Related

Read an ".sbt like" file for highly customizable configurations in Scala

I'd like to write a simple app to crawl/scrape some web content. The more I delve into the analysis, the more I realize that the instructions I need to give to the app in order to navigate through the site and get the content I wish it to extract, may be very peculiar depending on the target website structure.
The idea was to write some configuration files to define how the app should browse and scrape each specific site, but defining such behaviour could be challenging, unless you write in the configuration file some actual Scala code.
So, the idea is to write some code able to get a scraper object instance reading a file written in the .sbt format and inject some code in it.
First of all, I need to know where to start to achieve such task: what library should I use?
Could it be easier to write some sbt tasks and use sbt as the core of the app instead of writing one from scratch? What should be the limitations in this approach?
I apologize for being so general, but I don't have the slightest idea from where to start. I'd like you to head me to the right direction and post some docs to read.
Consider the app is meant to be a CLI tool, no graphical interface needed, then.

How can one sbt plugin set another plugin's settings then call that other plugin

I'm trying to augment an existing plugin, lets call it A-Plugin.
A-Plugin's main task uses the mappings setting.
However setting up the mappings setting is tedious for what I need and can be entirely automated. So I'm trying to write a plugin that calculates the correct mappings setting sets the mappings then calls A-Plugin's main task.
I have a task that does the calulation of mappings, but I cant' initialise mappings with it because settings can't depend on tasks, I also don't know how to call A-Plugin's task from mine when i'm ready.
This sounds like it should be a command but the best practice plugin guide says to avoid createing commands in plugins.
How can I do this? Am I on the right track or is there another idiom I should use?
Part of me is now thinking that I should just expose the function to calculate mappings and simply leave it up the the plugin user to set mappings from the function.... however this would run as soon as sbt was started... whereas I need to run it after some other tasks hove run.
Anyone know what to do?
Thanks
It's true that Plugins Best Practices says to generally try to avoid using commands first. However, if you can't achieve what you want using just settings and tasks, you should go ahead and reach for bigger hammer.
Also note:
One legitimate use of commands may be using plugin to access the build definition itself not the code. sbt-inspectr was implemented using a command before it became inspect tree.
In your case, if you're trying to dynamically set a setting, and then execute a task, that's sort of like rewiring the build definition, so I'd consider a candidate for a command. You'd still be careful implementing it to make sure it can handle multi-project etc.

How to conditionally exclude a scenario in cucumber

I am trying to exclude scenarios programmatically in cucumber. Testcases are OS dependent in my case. Say if underlying OS is Windows, I would like to skip certain scenarios. After some research on google I found out that there a place where you can hook up this logic in ruby i.e. AfterConfiguration. However, I am not able to find where I can hook this up to cucumber through scala.
I am also aware that it is not good practice to exclude scenarios but I have no choice.
First, add tags for the os-dependent scenarios (this can be at a feature file level by putting the tag at the top of the file).
#windows8
Scenario: Seeing extra feature XYZ in Windows 8
Then cucumber options that only use the tags for that os, or that ignore the tags for the other os. If you are using mvn, it might look like this:
mvn clean install -Dcucumber.options="--tags #windows8"

Automated testing developer environments

We use gradle as our build tool and use the idea plugin to be able to generate the project/module files. The process for a new developer on the project would look like this:
pull from source control.
run 'gradle idea'.
open idea and be able to develop without any further setup.
This all works nicely, but generally only gets exercised when a new developer joins or someone gets a new machine. I would really like to automate the testing of this more frequently in the same way we automate our unit/integration tests as part of our continuous integration process.
Does anyone know if this is possible and if there is any libraries for doing this kind of thing?
You can also substitue idea for eclipse as we have a similar process for those that prefer using eclipse.
The second step (with or without step one) is easy to smoke test (just execute the task as part of a CI build), the third one less so. However, if you are following best practices and regenerate IDEA files rather than committing them to source control, developers will likely perform both steps more or less regularly (e.g. every time a dependency changes).
As Peter noted, the real challenge is step #3. The first 2 ones are solved by your SCM plugin and gradle task. You could try automating the last task by doing something like this
identify the proper command line option, on your platform, that opens a specified intellij project from the command line
find a simple good enough scenario that could validate that the generated project is working as it should. E.g. make a clean then build. Make sure you can reproduce these steps using keyboard shortcuts only. Validation could be made by validating either produced artifacts or test result reports, etc
use an external library, like Robot, to program the starting of intellij and the running of your keyboards. Here's a simple example with Robot. Use a dynamic language with inbuilt console instead of pure Java for that, it will speed your scripting a lot...
Another idea would be to include a daemon plugin in intellij to pass back the commands from external CLI. Otherwise take contact with the intellij team, they may have something to ease your work here.
Notes:
beware of false negatives: any failure could be caused by external issues, like project instability. Try to make sure you only build from a validated working project...
beware of false positives: any assumption / unchecked result code could hide issues. Make sure you clean properly the workspace, installation, to have a repeatable state and standard scenario matching first use.
Final thoughts: while interesting from a theoretical angle, this automation exercise may not bring all the required results, i.e. the validation of the platform. Still it's an interesting learning experience and could serve as a material for a nice short talk, especially if you find out interesting stuff. Make it a beer challenger with your team when you have a few idle hours to try to see who can implement the fastest a working solution ;) Good luck!

How should a Dist::Zilla plugin give feedback to the user?

I have a couple of Dist::Zilla plugins that I wrote when I was very new to Moose and to Dist::Zilla both, and I'm currently trying to update them to make them a bit more robust, and less error-prone.
One thing I would like to do is to give the user feedback if I detect that they have given me contradictory or impossible instructions. Things like:
[ MyPlugin ]
include = all
exclude = all
Dist::Zilla does appear to have an (undocumented) internal logging system which I originally hooked into when I wrote my plugins, but which no longer seems to work (probably due to internal changes). So, how should I give the user feedback these days?
(Meant to put this in the comment but hit length limit).
Caveat: I've only written a couple of small dzil plugins myself, and am not very familiar with its internals.
dzil uses Log::Dispatchouli, which is also written by rjbs. Log::Dispatchouli is used by several other projects (including projects started by people other than rjbs), so it's not exactly an internal dzil logging system.
From what I understand, Log::Dispatchouli only has two logging levels, normal and debug. Debug logs are not normally seen in output; you have to enable debugging first. Normal (and debug) logs can be muted if you enable muting.
To enable debugging in dzil, add a -v command-line switch. This does not seem to be documented in 'dzil help' nor 'dzil help COMMAND'. But rjbs blogged about it.
Now to produce logs inside the dzil plugins, you just call $self->log(...) or $self->log_debug(...). The second one will be seen only if user passes -v option.