Module-Release

 view release on metacpan or  search on metacpan

script/release  view on Meta::CPAN


	# Enable parallel testing by setting $ENV{HARNESS_OPTIONS}
	release -j
	release -j8

=head1 DESCRIPTION

This is the prototype program for using C<Module::Release>. You should
modify it to fit your needs. If it doesn't do what you want, you can
change it however you like. This is how I like to release my modules,
and I'm happy to add features that do not get in my way. Beyond that,
you should write your own script to match your process.

This program automates Perl module releases. It makes the
distribution, tests it, checks that source control is up to date, tags
source control, and uploads it to the PAUSE.

By default this script assumes that you use Git as your source control
and relies mostly on L<Module::Release::Git>, which is an external
module. This distributes L<Module::Release::SVN>, but I haven't touched
that in years. There's still some code for CVS that I should probably
rip out.

=head2 Process

The release script checks many things before it actually releases the
file.  Some of these are annoying, but they are also the last line of
defense against releasing bad distributions.

=over 4

=item Read the configuration data

Look in the current working directory for C<.releaserc>.  See the
Configuration section.  If release cannot find the configuration file,
it dies.

=item Various sanity checks

These are related to various mistakes I've made at some point.

	* am I allowed to release from this branch (so, not an experimental branch)
	* have I listed all the prereqs?
	* is the version greater than what I've already released?

=item Test and make the distribution

Run make realclean, perl Makefile.PL, make test, make dist, make
disttest.  If testing fails, release dies.  make dist provides the
name of the distribution if LOCAL_FILE is not provided on the command
line. Too test the distribution against several perl binaries, see
the C<perls> configuration setting.

=item Check that source control is up-to-date

If there are modified files, added files, or extra files so that
source control complains, fail.

=item Check that any GPG signatures are correct

If C<gpg_signatures> is present in the config, load
L<Module::Release::VerifyGPGSignature> and verify the configured
signatures.

=item Upload to PAUSE

This program used to use FTP uploads, but PAUSE has turned off that feature.
Now it uploads through the web form.

=item Tag the repository

Use the version number (in the distribution name) to tag the
repository. You should be able to checkout the code from any release.

=back

=head2 Command-line switches

=over 4

=item -a

=item --automated-testing

Set $ENV{AUTOMATED_TESTING} to true. You can also set C<automated_testing>
in the configuration file

=item -c STRING

=item --changes STRING

Specify the F<Changes> file entry on the command line. If STRING does
not start with a C<*>, one will be added to the start along with a space.

    release -c "* some change"

translates to the F<Changes> entry with the date and one bullet item:

	3.11 2025-02-20T22:56:28Z
		* some change

STRING can also be a multiline string, but this will only append a C<*>
to the first line if it does not already have on. All lines will be
indented under the date though.

=item -C

=item --skip-changes

Skip the F<Changes> file. This is also the C<skip_changes> config option

=item -d

=item --skip-debug

Show debugging information. This is also the C<debug> config option

=item -D

=item --skip-dist

script/release  view on Meta::CPAN

		}
	elsif( $cpan eq '<undef>' ) {
		$release->_die( "Could not get CPAN version.\nSkip this CPAN version check with -V if you are sure you want to continue\n" );
		}
	elsif( version->parse($cpan) >= version->parse($dist) ) {
		$release->_die( "Local version <$dist> is not greater than current version <$cpan>\n" );
		}
	}


# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# check kwalitee
unless( $opts{k} // $release->config->skip_kwalitee  ) {
	$release->load_mixin( 'Module::Release::Kwalitee' );
	$release->_print("============ Testing for kwalitee\n");
	$release->clean;
	$release->build_makefile;
	$release->make;
	$release->dist;
	$release->check_kwalitee;
	}
else {
	$opts{t} or $release->_print( "Skipping kwalitee checks. Shame on you!\n" );
	}

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# check MANIFEST. When we run 'make manifest' nothing should be
# added or removed from MANIFEST
unless( $opts{'m'} // $release->config->skip_manifest ) {
	$release->_print("============ Checking MANIFEST\n");
	$release->load_mixin('Module::Release::MANIFEST');
	$release->clean;
	$release->build_makefile;
	$release->make;
	$release->check_MANIFEST;
	}


# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# check source repository (but do not commit)
# This should happen after everything else because I like to use
# release as my testing tool before I checkin. It will test but
# not release if VCS is dirty.
$release->_print("============ Checking source repository\n");

$release->check_vcs;

my $Version;
if ($skip_dist) {
	$Version = "?"; # Get from ?
	}
else {
	$release->dist unless( $release->local_file and -e $release->local_file );
	$Version = eval { $release->dist_version } // 'error?';
	}

$release->_debug( "dist version is <$Version>\n" );

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# check anything signed by GPG
if( $release->config->gpg_signatures ) {
	$release->_print("============ Checking GPG signatures\n");
	$release->load_mixin('Module::Release::VerifyGPGSignature');
	$release->check_all_gpg_signatures;
	}


# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# test with a bunch of perls
unless( $opts{T} // $release->config->skip_tests ) {
	my $old_perl = $release->get_perl;

	my @perls = $release->perls;
	my ($n, $N) = (1, scalar @perls);
	PERL: foreach my $perl ( @perls ) {
		$release->_print("============ Testing with $perl (", $n++, "/$N)\n");
		$release->set_perl( $perl ) or next;

		$release->clean;

		foreach my $mod ( grep m/\S/ => split m/\s*,\s*/ => $required ) {
			system "$perl -M$mod -e1 >/dev/null 2>&1";
			if( $? ) {
				warn "Prereq $mod not available\n";
				next PERL;
				}
			}

		$release->build_makefile;
		$release->make;
		$release->test;

		unless( $skip_prereqs ) {
			$release->check_prereqs;
			}
		else {
			$opts{t} or $release->_print( "Skipping prereq checks. Shame on you!\n" );
			}

		unless( $skip_dist ) {
			$release->dist;
			$release->disttest;
			}
		}

	$release->set_perl( $old_perl );
	}


# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# exit if this is a dry run. Everything following this changes
# things or uploads. Don't leave anything behind.
if( $opts{t} // $release->config->dry_run ) {
	$release->_print("============ Cleaning up\n");
	$release->_print( "This is a dry run, so stopping. Cleaning up.\n" );
	$release->distclean;
	unlink glob( '*.tar *.tgz *.tar.gz *.tar.bz *.tar.bz2 *.tbz *.zip' );
	exit;
	}


# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# CPAN::Spec::Changes
$release->_print("============ Getting Changes\n");



( run in 0.650 second using v1.01-cache-2.11-cpan-df04353d9ac )