Skip to content
Back to skills

Getty Perl Distribution

ASecurity

Use when creating a Perl CPAN distribution or bringing an existing one in line with [@Author::GETTY] — dist.ini, cpanfile, Changes, lib/, t/, CI scaffolding.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 4, 2026
ai-agentsbashtestinggit

Works with

  • cli

Security analysis

A100/100

Pro scans all 10 files and shows the line behind each finding

Scanned October 4, 2026

npx -y skills add Getty/skills --skill getty-perl-distribution --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Getty Perl Distribution?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Getty Perl Distribution
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/getty-getty-perl-distribution/badge)](https://www.skillsdirectory.com/skills/getty-getty-perl-distribution)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: getty-perl-distribution
description: Use when creating a Perl CPAN distribution or bringing an existing one in line with [@Author::GETTY] — dist.ini, cpanfile, Changes, lib/, t/, CI scaffolding.
user-invocable: true
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
---

# Perl Distribution

Create or polish a Perl distribution matching Getty's workspace conventions.

## Inputs the skill expects to resolve before writing

| What | Resolution order |
|---|---|
| `dist`      | dash-form (`WWW-Foo`) — from user arg or from the checkout dir name (`p5-www-foo` → `WWW-Foo`) |
| `module`    | colon-form (`WWW::Foo`) — derived from `dist` by `s/-/::/g` |
| `abstract`  | one-line `# ABSTRACT:` from the first non-empty existing `lib/**/*.pm`, else ask |
| `author`    | `Torsten Raudssus <getty@cpan.org>` |
| `copyright_holder` | `Torsten Raudssus <torsten@raudssus.de> L<https://raudssus.de/>` |
| `copyright_year`   | current year |
| `license`   | `Perl_5` |
| `irc`       | search sibling `p5-*` checkouts' `dist.ini` for an existing `irc =` line in the same topic cluster; if none found, ask the user (never make one up) |

## Sibling reference

Before writing, read **one** existing sibling dist that is closest in topic
(e.g. for a new `WWW-*` HTTP client, read an existing `WWW-*` client dist —
same shape, same layout). Match its layout exactly:

- `dist.ini`
- `cpanfile` (split `on test` / `on develop` if the sibling does)
- `Changes` (`{{$NEXT}}` marker + one `0.001` entry with a bullet list)
- `README.md` (Synopsis → Description → one example per public method → License)
- `.gitignore` (copy sibling's, substituting the dist name in the build-dir ignore line)
- `LICENSE` — **not** copied from the sibling: generated with `dzil genlicense`
  and committed (see *After writing*). Most existing dists predate the check and
  have no LICENSE at all, so the sibling is not a guide here
- `t/00-load.t` using `Test::LoadAllModules` OR `use_ok` — match what the sibling uses
- Any additional `t/NN-*.t` the author convention calls for (often `10-*`, `20-*` topical tests)
- `.github/workflows/ci.yml` — copy the sibling's if it has one, else the
  fallback template (see CI workflow below)

Do NOT diverge from the sibling's style even if it feels outdated. Workspace
consistency beats "modern best practice."

## Test file conventions

- **Every `.t` opens with a shebang:** `#!/usr/bin/env perl`, then `use strict; use warnings; use Test::More;`
- **Close with `done_testing;`** — never `plan tests => N`.
- **Ship a load test** that `use_ok`s every module of the distribution, either via `Test::LoadAllModules` or an explicit `qw( ... )` list — match the sibling.

```perl
#!/usr/bin/env perl
use strict;
use warnings;
use Test::More;

for (qw(
  WWW::Foo
  WWW::Foo::Client
)) {
  use_ok($_);
}

done_testing;
```

## dist.ini header

Open every `dist.ini` with the metadata block, aligned on `=`:

```
name    = WWW-Foo
author  = Torsten Raudssus <getty@cpan.org>
license = Perl_5
copyright_holder = Torsten Raudssus <torsten@raudssus.de> L<https://raudssus.de/>
copyright_year   = 2026
```

`author` carries the **cpan.org** address — that is what links the release to
the PAUSE account across the CPAN subsystems. `copyright_holder` carries the
everyday address plus the homepage link. Never swap the two.

Then the plugin bundle. For Getty's own CPAN work that is `[@Author::GETTY]` —
its options are documented in `getty-perl-release-author-getty`.

## CI workflow

Every dist gets a `.github/workflows/ci.yml`. The repetitive Dist::Zilla CI
mechanics live ONCE in a shared **composite action** in the bundle repo
(`Getty/p5-dist-zilla-pluginbundle-author-getty/.github/actions/dzil-test`), so
the per-dist workflow only carries its matrix and any system-library install:

```yaml
- uses: Getty/p5-dist-zilla-pluginbundle-author-getty/.github/actions/dzil-test@main
```

The action runs `dzil authordeps` + `dzil listdeps --author` + `dzil test`. The
`--author` flag installs develop-phase author-test deps (e.g. `Test::Pod`, which
`[PodSyntaxTests]` registers). **Never fake `Test::Pod` into the cpanfile's
`on test`** — that is exactly the bug this setup removes.

- Pure-Perl dist: use the fallback template `templates/github-ci.yml` as-is.
- Alien / XS dist: add the `apt-get`/`brew` system-library step(s) before the
  action, and a `share-build` job passing `install-type: share`. Copy the
  layout from an existing Alien dist of the same shape.

## Templates

Fallback templates (used only when no suitable sibling exists) live in this
skill's `templates/` directory: `dist.ini`, `cpanfile`, `Changes`,
`README.md`, `claude-md.md`, `lib_Module.pm`, `t_00-load.t`,
`t_01-basic.t`, `github-ci.yml`. Placeholders use `{{$name}}` — substitute
with `sed` or equivalent. Rename `lib_Module.pm` → `lib/<Path>/<Name>.pm`,
`t_*.t` → `t/*.t`, `claude-md.md` → `CLAUDE.md`, and `github-ci.yml` →
`.github/workflows/ci.yml`. Every template is named so that it stays inert
where the skill is installed: the whole skill directory lands under
`.claude/skills/`, and a file literally called `CLAUDE.md` there is picked up
as instructions.

## Handcheck rules

- Author line must be `getty@cpan.org` — only the CPAN email, no name
  with valid email + website. Refuse to fabricate either.
- Copyright year in `dist.ini` and `Changes` must match.
- IRC channel is optional but, if included, must be a real channel. Ask rather
  than invent.
- Every module under `lib/` and executable under `bin/` carries its own
  `our $VERSION = '...';`, set to the NEXT (unreleased) version —
  `[@Author::GETTY]` rewrites it via `RewriteVersion::Transitional`, and a file
  without one ships versionless. See `getty-perl-core`.

## After writing

Write the licence file and track it. `[@Author::GETTY]` aborts the build without
a committed `LICENSE`, and the `git add` is not optional — the bundle gathers
through `Git::GatherDir`, which only sees tracked files:

```bash
dzil genlicense
git add LICENSE
```

Then run `dzil test` inside the dist directory and surface the output. Do NOT
`dzil release` unless the user explicitly asks.

## Related

- `getty-create-software` — parent orchestrator; loads this skill for Perl projects.
- `perl-release-dist-ini` — loaded when *editing* an existing `dist.ini`.
- `getty-perl-release-author-getty` — loaded when *releasing*.
- `getty-perl-core` — Getty's house Perl style rules.

Files in this skill

  • SKILL.md6.4 KB
  • templates/Changes90 B
  • templates/README.md395 B
  • templates/claude-md.md1.6 KB
  • templates/cpanfile138 B
  • templates/dist.ini183 B
  • templates/github-ci.yml1.3 KB
  • templates/lib_Module.pm419 B
  • templates/t_00-load.t93 B
  • templates/t_01-basic.t106 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…