ASPEER-MakeMaker-Markdown-Publish
view release on metacpan or search on metacpan
Installation
Install the released distribution and its prerequisites from CPAN:
cpanm ASPEER::MakeMaker::Markdown::Publish
GitHub Attestations
The release workflow generates GitHub artifact attestations for
distribution archives. Install the GitHub CLI with gh attestation
support and authenticate with gh auth login.
To verify a CPAN release archive separately, download
ASPEER-MakeMaker-Markdown-Publish-VERSION.tar.gz from MetaCPAN or a CPAN
mirror, replace VERSION, and run:
gh attestation verify ASPEER-MakeMaker-Markdown-Publish-VERSION.tar.gz --repo aspeer/pm-ASPEER-MakeMaker-Markdown-Publish
A successful verification confirms that the archive checksum matches an
attestation from this repository. The workflow publishes the same
archive to GitHub Releases and CPAN. Older releases and GitHub's
Install the released distribution and its prerequisites from CPAN:
```sh
cpanm ASPEER::MakeMaker::Markdown::Publish
```
## GitHub Attestations
The release workflow generates [GitHub artifact attestations](https://docs.github.com/en/actions/concepts/security/artifact-attestations)
for distribution archives. Install the [GitHub CLI](https://cli.github.com/)
with `gh attestation` support and authenticate with `gh auth login`.
To verify a CPAN release archive separately, download
`ASPEER-MakeMaker-Markdown-Publish-VERSION.tar.gz` from MetaCPAN or a CPAN
mirror, replace `VERSION`, and run:
```sh
gh attestation verify ASPEER-MakeMaker-Markdown-Publish-VERSION.tar.gz --repo aspeer/pm-ASPEER-MakeMaker-Markdown-Publish
```
A successful verification confirms that the archive checksum matches an
SECURITY.md view on Meta::CPAN
Please report security vulnerabilities via GitHub private vulnerability reporting:
https://github.com/aspeer/pm-ASPEER-MakeMaker-Markdown-Publish/security/advisories/new
If you cannot use GitHub, report the issue privately to Andrew Speer
<andrew.speer@isolutions.com.au>. Do not report vulnerabilities through public
issues, pull requests, mailing lists, social media, or other public forums.
Include the affected version, Perl version and operating system when relevant,
reproduction steps or a test case, relevant logs or code, whether exploitation
is known, and whether you want public credit. Do not include credentials or
other sensitive information unless strictly necessary and safe to share.
For triage or CVE coordination, you may also contact the CPAN Security Group at
cpan-security@security.metacpan.org. For a compromised PAUSE account, contact
pause-admin@perl.org.
## Supported Versions
Security fixes are normally made against the latest release on CPAN. Older
lib/ASPEER/MakeMaker/Markdown/Publish.pm view on Meta::CPAN
without replacing it. It is passed unchanged to `Markdown::Publish` and
cannot be combined with `config`. MkDocs accepts supplemental YAML; the Node
publishers accept the extension functions documented by their engine modules.
For Workers Static Assets, place `wrangler.jsonc` or `wrangler.json` in the
project root. `publish_cloudflare` discovers those names in that order, so no
Cloudflare publication metadata is needed for the usual layout. Set
`cloudflare => {config => 'deploy/wrangler.docs.jsonc'}` inside `publish` to
select a file elsewhere. Optionally set `wrangler` to the executable path or
`environment` to an authored Wrangler environment in the same `cloudflare`
hash. Wrangler uses its own login or environment for authentication; do not
put credentials in metadata. Deployment does not change Git.
A minimal project-root `wrangler.jsonc` is:
```jsonc
{
"name": "example-documentation",
"compatibility_date": "2026-09-29"
}
```
lib/ASPEER/MakeMaker/Markdown/Publish.pm view on Meta::CPAN
without replacing it. It is passed unchanged to C<Markdown::Publish> and
cannot be combined with C<config>. MkDocs accepts supplemental YAML; the Node
publishers accept the extension functions documented by their engine modules.
For Workers Static Assets, place C<wrangler.jsonc> or C<wrangler.json> in the
project root. C<publish_cloudflare> discovers those names in that order, so no
Cloudflare publication metadata is needed for the usual layout. Set
C<<< cloudflare => {config => 'deploy/wrangler.docs.jsonc'} >>> inside C<publish> to
select a file elsewhere. Optionally set C<wrangler> to the executable path or
C<environment> to an authored Wrangler environment in the same C<cloudflare>
hash. Wrangler uses its own login or environment for authentication; do not
put credentials in metadata. Deployment does not change Git.
A minimal project-root C<wrangler.jsonc> is:
{
"name": "example-documentation",
"compatibility_date": "2026-09-29"
}
The target supplies the generated site using Wrangler's C<--assets> option, so
lib/ASPEER/MakeMaker/Markdown/Publish.pm.md view on Meta::CPAN
without replacing it. It is passed unchanged to `Markdown::Publish` and
cannot be combined with `config`. MkDocs accepts supplemental YAML; the Node
publishers accept the extension functions documented by their engine modules.
For Workers Static Assets, place `wrangler.jsonc` or `wrangler.json` in the
project root. `publish_cloudflare` discovers those names in that order, so no
Cloudflare publication metadata is needed for the usual layout. Set
`cloudflare => {config => 'deploy/wrangler.docs.jsonc'}` inside `publish` to
select a file elsewhere. Optionally set `wrangler` to the executable path or
`environment` to an authored Wrangler environment in the same `cloudflare`
hash. Wrangler uses its own login or environment for authentication; do not
put credentials in metadata. Deployment does not change Git.
A minimal project-root `wrangler.jsonc` is:
```jsonc
{
"name": "example-documentation",
"compatibility_date": "2026-09-29"
}
```
t/01-targets.t view on Meta::CPAN
# The runtime publisher stub records exactly what the generated target passes
#
blurp('local lib/Markdown/Publish.pm', <<'PUBLISH_STUB');
package Markdown::Publish;
use JSON::PP qw(encode_json);
sub new {my ($class, $config_hr)=@_; return bless({config => $config_hr}, $class)}
sub run {
my ($self, $action)=@_;
open(my $output_fh, '>>', 'target.log') || die "unable to write target log: $!";
print {$output_fh} encode_json({config => $self->{'config'}, action => $action}), "\n";
close($output_fh) || die "unable to close target log: $!";
return 1;
}
1;
PUBLISH_STUB
blurp('lib/Sample.pm', "package Sample;\nour \$VERSION='0.001';\n1;\n");
blurp('lib/Sample.pm.md', "# NAME\n\nSample - generated documentation target fixture\n");
blurp('README.md', "# Sample\n\nGenerated documentation target fixture.\n");
blurp('MANIFEST', "lib/Sample.pm\nlib/Sample.pm.md\nREADME.md\ndoc/guide.md\n");
blurp('doc/guide.md', "# Guide\n\nText.\n");
blurp('Makefile.PL', <<'MAKEFILE_PL');
t/01-targets.t view on Meta::CPAN
is(system($^X, '-MASPEER::MakeMaker::Markdown::Publish', 'Makefile.PL'), 0,
'Makefile regenerates after documentation updates VERSION_FROM');
is(system($make, 'publish_build'), 0, 'generated build target succeeds');
is(system($make, 'publish_serve'), 0, 'generated local server target delegates');
is(system($make, 'publish_gh'), 0,
'generated local publication target delegates');
is(system($make, 'publish_gh-push'), 0,
'generated publication push target delegates');
is(system($make, 'publish_cloudflare'), 0,
'generated static-assets deployment target delegates');
my @target=map {decode_json($_)} grep {length($_)} split(/\n/, slurp('target.log'));
is_deeply(
[map {$_->{'action'}} @target],
['build', 'serve', 'gh', 'gh-push', 'cloudflare'],
'generated targets dispatch the selected action'
);
my $default_config_hr={%{$config_hr}, name => 'Sample'};
is_deeply($target[0]{'config'}, $default_config_hr,
'distribution module name supplies the default site title');
# An explicit publication name overrides the distribution module name
#
my $configured=slurp('Makefile.PL');
$configured=~s/(publish\s*=>\s*\{\n)/$1 name => 'Sample documentation',\n/ ||
die "unable to construct named publication fixture";
blurp('Makefile.PL', $configured);
is(system($^X, '-MASPEER::MakeMaker::Markdown::Publish', 'Makefile.PL'), 0,
'Makefile.PL accepts an explicit publication name');
is(system($make, 'publish_build'), 0,
'generated build target accepts the explicit publication name');
@target=map {decode_json($_)} grep {length($_)} split(/\n/, slurp('target.log'));
is($target[-1]{'config'}{'name'}, 'Sample documentation',
'explicit publication name overrides the default');
# Explicit and composed Pod imports remain idempotent
#
my $explicit=slurp('Makefile.PL');
$explicit=~s/(use ExtUtils::MakeMaker;\n)/$1use ASPEER::MakeMaker::Markdown::Pod;\n/ ||
die "unable to construct explicit Pod import fixture";
blurp('Makefile.PL', $explicit);
t/01-targets.t view on Meta::CPAN
use ExtUtils::MakeMaker;
WriteMakefile(
NAME => 'Sample',
VERSION_FROM => 'lib/Sample.pm',
);
MAKEFILE_PL
is(system($^X, '-MASPEER::MakeMaker::Markdown::Publish', 'Makefile.PL'), 0,
'Makefile.PL accepts omitted publication metadata');
is(system($make, 'publish_cloudflare'), 0,
'Cloudflare target delegates without publication metadata');
@target=map {decode_json($_)} grep {length($_)} split(/\n/, slurp('target.log'));
is_deeply($target[-1]{'config'}, {name => 'Sample'},
'Cloudflare target passes only the default distribution name');
chdir($cwd) || die "unable to restore cwd $cwd: $!";
done_testing();
( run in 0.501 second using v1.01-cache-2.11-cpan-eca53f54451 )