Search code examples
perlcpan

Is there a way to run perl code during cpan install after tests have passed?


I have my own cpan mirror which has some injected modules for our internal use only. I would like to run some perl code during cpan install. Currently I'm injecting the code directly to Makefile.PL, but the problem is that that it is run before "make test". I would like the code being run only after the distributions tests have passed.

One option would be to inject the code in the end of the last test file, but how do I know if all tests in all testfiles have passed? Test::More->builder->is_passing seems to know only about the current test file.


Solution

  • One option (if you are using ExtUtils::MakeMaker) is to define a MY::test function in Makefile.PL to (conditionally) add an extra task. Something like

     # Makefile.PL
     ...
     sub MY::test {
        my $text = shift->SUPER::test(@_);  # original 'test' action for this system
        if ($ENV{BOOM}) {
            $text =~ s/^(test ::.*)$/$1 GO-BOOM/m;
            $text .= q~
    GO-BOOM ::
        $(PERL) -E 'say "BOOM!"'
    ~;
        # note: important to use tab, not spaces, before "$(PERL) ..."
        }
        return $text;
     }
    

    In the Makefile, the test action will now either look like

    test :: $(TEST_TYPE) subdirs-test GO-BOOM
    ...
    GO-BOOM ::
            $(PERL) -E 'say "BOOM!"'
    

    or

    test :: $(TEST_TYPE) subdirs-test
    

    depending on what happened in Makefile.PL. (These are typical linux specs in the Makefile. Your results may vary).

    If you have defined the BOOM environment variable when you ran Makefile.PL, and if the prior actions related to make test are successful, then the test action will also perform the GO-BOOM action. But if a test fails, then GO-BOOM will not run.

    $ BOOM=1 perl Makefile.PL
    $ make test TEST_FILES=t/test-that-will-pass.t
    PERL_DL_NONLAZY=1 "/usr/bin/perl" "-MExtUtils::Command::MM" "-MTest::Harness" "-e" "undef *Test::Harness::Switches; test_harness(0, 'blib/lib', 'blib/arch')" t/test-that-will-pass.t
    t/test-that-will-pass .. ok    
    All tests successful.
    Files=1, Tests=16,  4 wallclock secs ( 0.01 usr  0.01 sys +  0.06 cusr  0.01 csys =  0.09 CPU)
    Result: PASS
    "/usr/bin/perl" -E 'say "BOOM!"'
    BOOM!
    
    $ make test TEST_FILES=t/test-that-will-fail.t
    PERL_DL_NONLAZY=1 "/usr/bin/perl" "-MExtUtils::Command::MM" "-MTest::Harness" "-e" "undef *Test::Harness::Switches; test_harness(0, 'blib/lib', 'blib/arch')" t/test-that-will-fail.t
    t/test-that-will-fail.t .. 1/? 
    #   Failed test at t/test-that-will-fail.t line 2.
    # Looks like you failed 1 test of 1.
    t/test-that-will-fail.t .. Dubious, test returned 1 (wstat 256, 0x100)
    Failed 1/1 subtests 
    
    Test Summary Report
    -------------------
    t/test-that-will-fail.t (Wstat: 256 Tests: 1 Failed: 1)
      Failed test:  1
      Non-zero exit status: 1
    Files=1, Tests=1,  0 wallclock secs ( 0.01 usr  0.01 sys +  0.03 cusr  0.00 csys =  0.05 CPU)
    Result: FAIL
    Failed 1/1 test programs. 1/1 subtests failed.
    Makefile:938: recipe for target 'test_dynamic' failed
    make: *** [test_dynamic] Error 1
    

    (no boom)