---
name: perl-release
description: Use when publishing Perl modules to PAUSE/CPAN, releasing distributions, or when user mentions "minil release", "cpan upload", or "publish to PAUSE"
---

# Publishing Perl Modules to PAUSE

## Overview

Release Perl distributions to CPAN via PAUSE using Minilla. **Uploads are permanent** - verify everything before release.

## Pre-Release Checklist

Run ALL checks before release:

```bash
# 1. PAUSE credentials
test -f ~/.pause && echo "OK" || echo "MISSING - create ~/.pause"

# 2. Tests (use -l flag for lib path)
carton exec -- prove -v -l t/

# 3. Current version
grep -E "^our \$VERSION" lib/**/*.pm

# 4. Changes since last release
git log --oneline $(git describe --tags --abbrev=0 2>/dev/null || echo HEAD~10)..HEAD

# 5. Changes file has content
head -20 Changes

# 6. LICENSE file exists and is tracked (CRITICAL)
test -f LICENSE && echo "LICENSE exists" || echo "MISSING LICENSE"
git check-ignore -v LICENSE 2>&1 | grep -q LICENSE && echo "WARNING: LICENSE is gitignored!" || echo "LICENSE tracking OK"
```

## Fix Missing LICENSE

If LICENSE is missing or gitignored:

```bash
# Create LICENSE for Perl_5 license
cat > LICENSE << 'EOF'
This software is copyright (c) 2024 by Your Name <your@email.com>.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

Terms of the Perl programming language system itself

a) the GNU General Public License as published by the Free
   Software Foundation; either version 1, or (at your option) any
   later version, or
b) the "Artistic License"
EOF

# Remove from .gitignore if present
sed -i '' '/^\/LICENSE$/d' .gitignore

# Commit
git add LICENSE .gitignore
git commit -m "Add LICENSE file for CPAN release"
```

## Install Release Dependencies

Minilla requires these modules (install once per system):

```bash
# Core release dependencies
cpanm Version::Next CPAN::Uploader

# SSL dependencies (for HTTPS upload)
# On macOS with Homebrew OpenSSL:
OPENSSL_PREFIX=$(brew --prefix openssl) cpanm --force Net::SSLeay
cpanm IO::Socket::SSL LWP::Protocol::https
```

## Release Commands

```bash
# Dry run - test build without upload
carton exec minil test

# Interactive release (prompts for version and confirmation)
carton exec minil release

# Non-interactive release (for automation)
# Replace VERSION with actual version (e.g., 0.01)
printf "VERSION\ny\n" | carton exec minil release
```

Minilla automatically:

- Prompts for version (or bumps)
- Updates Changes file with release date
- Builds tarball
- Runs tests
- Creates git tag
- Pushes to origin
- Uploads to PAUSE

## Setting Up ~/.pause

```text
user YOUR_PAUSE_USERNAME
password YOUR_PAUSE_PASSWORD
```

Get credentials at <https://pause.perl.org/> (request account if needed).

## Common Issues

| Issue | Fix |
| --- | --- |
| No ~/.pause | Create file with PAUSE credentials |
| Tests fail | Fix tests; use `prove -v -l t/` to include lib/ |
| Missing LICENSE | Create LICENSE file (see above) |
| LICENSE gitignored | Remove `/LICENSE` from .gitignore, commit LICENSE |
| Version::Next missing | `cpanm Version::Next` |
| CPAN::Uploader missing | `cpanm CPAN::Uploader` |
| Net::SSLeay build fails | `OPENSSL_PREFIX=$(brew --prefix openssl) cpanm --force Net::SSLeay` |
| IO::Socket::SSL missing | `cpanm IO::Socket::SSL LWP::Protocol::https` |
| Upload rejected | Check PAUSE permissions, namespace ownership |

## Post-Release

- Verify on <https://metacpan.org/> (indexing takes 1-2 hours)
- Confirm git tag: `git tag`
- Confirm push: `git log --oneline -1 origin/master`
