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

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.

Related

Block inclusion of a Perl module unless explicitly included

I have a Perl application which is used in two contexts: It can be used as a diagnostic tool which displays information about a system, or as a testing tool which sends Modbus commands to that system. The problem I have is that allowing the user to send commands to the system in a diagnostic context is a potential safety risk, so I want to create two executables: A testing version that includes the Modbus module and a diagnostic one that does not.
My current solution is to include the Modbus module like this:
BEGIN { eval { require Modbus; }; Modbus->import; }
This only includes the Modbus module if I use the option -M Modbus while building the .exe with PAR Packager. The issue with this approach is that it fails unless this is the only place where Modbus is imported. So if another developer who isn't aware of this risk comes along, it only takes one require statement to bypass this fix.
Is there a way for me to prevent a specific module from being included in the executable unless I explicitly want it to be (either with the -M option or some other method)? I've been trying to figure something out with Devel::Hide, but haven't had much luck. All the solutions I've found so far fail the "other developer who doesn't know about this" test.
I'm using Strawberry Perl 5.20.3.3, but I can upgrade if necessary.
When I've done this sort of thing, I've created a small module that is included if it is present and not included if it is not:
eval { require MaybeItsThere }
In my Makefile (or whatever build system you want), I have targets for development and production builds. One of the subtasks for the dev build creates that MaybeItsThere file. It can also set whatever it needs for PERL5LIB and so on such that only the dev build can load it.
However, as you say, the enterprising developer can quickly find out what they need to do to get the features they want.
Having read through your comments, it seems that you're not going to be able to enforce correct usage. (You gave examples how the module has already been misused by people sidestepping your build process.) I would suggest an alternative approach.
Document the problem at that place where someone would find a workaround.
In other words, if some other developers is going to look at the code or at the build to see the name of the missing module, let them see a warning about the dangers right there. Put a comment block explaining why the Modbus module should only be used when diagnostics are disabled or filtered. Make the build's failure put a warning right there at the same place as the name of the missing module; use a die "Modbus should not be used when user interaction is enabled."; or something similar to convey the message in the same place where the other developer would be looking for the solution.
Ultimately, you can't force someone to use your build tools, but you can try to educate them while they're trying to work around you, instead of documenting the problem somewhere else that they might not see.

My Perl module from CPAN won't install, what do I do?

This is a canonical question for the above problem, inspired by this answer and this question. Please edit and improve it.
I'm trying to install a module from CPAN, using the CPAN/cpanm/CPANPLUS client. However, I'm getting build or test errors when I try to install it. What should I do?
Does it build at all?
The first thing to consider is, is your module building at all? If it isn't building, you should check for existing bug reports, file one if necessary, and perhaps try to fix the issue yourself (steps 2 and 3b/3c below).
If it builds but tests fail, follow these steps.
1. Determine if the test is valid
The purpose of these tests is to test. If there's a problem, you need to know about it, and not sweep it under the rug. Resolve the issue one way or another. Is there a problem with something on your system, or is this a problem with the test itself. If this is a problem with the test, does it still affect you? If this is a system problem, is this something you might run into? For example, let's say there's a test that checks for connectivity between your system and a Windows system. If you don't connect to Windows systems, maybe that particular test doesn't apply to you.
2. Check MetaCPAN for bug reports
If you have a test failure, go to the MetaCPAN webpage for that module, and check the left hand side for RT issues to see if someone else is getting the same errors. If no one is, you should open an RT ticket, or a ticket in the project's bug tracker of choice.
There may be patches available from other users. If the patches make sense to you, you can try applying them and rerunning the tests.
You can also click on the Testers link on MetaCPAN. The QA testers webpage will show you the various Perl versions, module versions, platforms, and show you which tests are failing on particular platforms on which versions. You might need to install an alternative version of the module.
At this point, there are a few paths you can take.
3a. Force the installation
Only once you've determined that the failed test doesn't necessarily apply to you, do a force install:
cpan> force install Date::Calc
This will run through the entire install, except that it will skip all testing. (Or maybe it still tests, but doesn't fail if a test fails.). The module will still fail on compiler errors, or if something can't get written to your system. It merely ignores tests.
This should be the last desperate attempt to get something installed. You've should have already resolved that the failed tests are bugs or not meaningful for you. Or, someone is standing beside you with a gun to your head saying, "Install that module, or I'll pull the trigger!".
3b. Find an alternative module
Or, you can decide to use another module. CPAN is full of various approaches to problems (TMTOWTDI), so there many be one there that does what you want.
3c. Write some code
Or, you can analyze why the test is failing and either fix the module or the code. Bug reports with potential patches are often appreciated by busy module authors. If it doesn't look like the author wants to take your fix, you can always fork an existing module, or write a fresh one.
If the author has gone MIA, you may be able to adopt the module and maintain it yourself. The general process for adopting a module is first to try to submit code to the author that fixes it, and then wait a while, maybe a month, for the author to pick it up. If there's no response, try alternative means of contact, email, Google+, whatever you can find. After that, you can go on Perl IRC chats, mailing lists, etc, looking for someone who knows where the author might be. If none of that works after a few months, the PAUSE admins can investigate and turn the module over to you.
This is based on this excellent answer

perl: new cpan module maker? local configuration text files and executables, too?

I am writing a perl program that I want to share with others, eventually via cpan. it's getting to the point where I should start thinking about this on a bigger scale.
a decade ago, I used the h2xs package maker once. is this still the most recommended way to get started? there used to be a couple of alternatives. because I am starting from scratch with very little recollection, anything simple will do at this point.
I need to read a few long text files (not perl modules) for configuration. where do I put them and how do I access them, no matter where the module is installed? (FindBin?) _DATA_ is inconvenient.
I need to provide an executable (linux and osx). can putting an executable into the user's path be part of the module installation? (how?)
I would like to be able to continue developing it, run it for test purposes, have a new version, repack it, and reupload it easily.
before uploading to cpan, can I share a cpan bundle for easy local installation to downloaders and testers?
# cpan < mybundle.cpanbundle
advice appreciated.
regards,
/iaw
If anything I say conflicts with Andy Lester, listen to him instead. He knows more than I ever will.
Module::Starter is a good, simple way to generate module scaffolding. My take is it's been the default for this sort of thing for a few years now.
For configuration/support files, I think you probably want File::ShareDir. Might be worth considering Data::Section if it's just a matter of needing multiple __DATA__ sections though.
You can certainly put scripts in the bin subdirectory of your distribution, the build tool will put it in the right place at install time.
A build tool will take care of the work-flow you describe.
Bundles are something different. You make a distribution and share the tarball/archive.
If you set up PERL5LIB appropriately, then repeat make test, make install, make dist to your heart's content. For development/sharing purposes a lot of projects do their work on github or similar - makes it easy to share. They have private accounts for business purposes too. Very useful if you want to rewind and see where/when a problem was introduced.
If you get a copy of cpanm (simple to install, fairly lightweight) then it can install from a tar.gz file or even direct from a git repository. You can also tell it to install to a local dir (local::lib compatible - another utility that's very useful).
Hopefully that's reasonably up-to-date as of 2014. You may see Dist::Zilla mentioned for module development. My understanding is that it's most useful for those with a large family of CPAN distributions to manage. Oh - if you (or other readers) aren't aware of them, do check out autodie and Try::Tiny around errors and exceptions, Moose (for a full-featured object-oriented framework) and Moo (for a smaller lightweight version).
I think that advice is all reasonably non-controversial. I find cpanm to be much more pleasant than the "full" cpan client, and Moo seems pretty popular nowadays too.
Take a look at Module::Starter and its much more capable (and complex) successor Dist::Zilla.
Whatever you do, don't use h2xs. Module::Starter was created specifically because h2xs was such an inappropriate tool for creating distributions.

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!

What are the strengths/weaknesses of ShipIt vs Dist::Zilla?

I started using Dist::Zilla several months ago. However, at YAPC::NA someone mentioned that they use ShipIt instead. Then today I noticed a .shipit file in miyagawa's cpanminus directory on github, so I decided to look into it some more...
My initial impression is that ShipIt has a subset of what is available with Dist::Zilla, but I don't want to jump to conclusions. So, for those who have had experience with both, what are the strengths/weaknesses of ShipIt vs Dist::Zilla?
crossposted at perlmonks
I'm the author of Dist::Zilla.
I evaluated ShipIt pretty extensively before choosing to go ahead and write Dist::Zilla, and initially they covered almost exactly the same problem space: doing all the boring grunt work of building and uploading a CPAN distribution. All of the features that Dist::Zilla now has beyond ShipIt are later additions, more or less.
If you only need the features of ShipIt, I still advise you to strongly consider Dist::Zilla, for one very simple reason: hackability. If I had been able to not write something new, I would've used ShipIt, but I found it to be underdocumented and difficult to extend. Its plugins were not generic enough and the core behavior made too many assumptions about how you'd like to work.
Dist::Zilla was inspired specifically by this problem: it turned everything into a plugin, and every plugin was given a very, very small interface so that its assumptions would be forcibly limited.
One benefit of ShipIt over Dist::Zilla is that ShipIt has (to the best of my knowledge) no plugins that will alter the way you actually write your code. This means your documentation will still look the same, you will still have a Makefile.PL, and so on. Some hackers don't like that so many DZ-based dists fundamentally change the assumptions of how to test and build CPAN code from its source repository. ShipIt will never change that.
It's possible to avoid using any such plugins with Dist::Zilla, but in general my experience is that people do use them, almost always, in one form or another.
As far as I can tell, my initial impressions were correct.
ShipIt provides functionality for releasing distributions:
keeping track of version numbers
integrating with version control
uploading to CPAN
displaying the changelog file in an editor so that you can edit it before release.
Dist::Zilla, by default, provides the ability to upload distributions to CPAN with a single command (i.e. dzil release). Dist::Zilla also has functionality for creating new distributions (i.e. dzil new My::New::Module). It also automatically generates so many of the files that I used to have to maintain by hand.
Using plugins, Dist::Zilla seems able to provide most, if not all, of the functionality available with ShipIt. It is also relatively easy to add brand new features using plugins.