| name | Plugin Publish |
| description | Publish bundled plugin packages to local, marketplace, or GitHub Releases with dry-run and validation modes |
plugin.publish
Overview
plugin.publish is the publication tool that distributes your bundled Betty Framework plugin packages to various targets. It validates package integrity via SHA256 checksums and handles publication to local directories, Claude Marketplace endpoints, or GitHub Releases with automatic creation support. Includes --dry-run and --validate-only modes for safe testing.
Purpose
Automates secure plugin distribution by:
- Validating SHA256 checksums to ensure package integrity
- Publishing to local directories for testing and archival
- Uploading to Claude Marketplace API endpoint (simulated, ready for production)
- Creating GitHub Releases automatically using gh CLI
- Tracking publication metadata for auditing and governance
- Testing with dry-run mode before actual publication
- Validating packages without publishing using validate-only mode
This ensures consistent, traceable, and secure plugin distribution across all deployment targets.
What It Does
- Validates Package: Verifies the .tar.gz file exists and is readable
- Calculates Checksums: Computes MD5 and SHA256 hashes for integrity verification
- Validates SHA256: Compares against expected checksum from manifest.json
- Loads Metadata: Extracts plugin info from manifest.json (name, version, author, etc.)
- Publishes to Target:
- local: Copies to
dist/published/with metadata - marketplace: POSTs JSON metadata to Claude Marketplace API (simulated)
- gh-release: Creates GitHub Release using gh CLI (with auto-create option)
- local: Copies to
- Supports Modes:
- --dry-run: Shows what would be done without making changes
- --validate-only: Only validates checksums without publishing
- --auto-create: Automatically creates GitHub Release using gh CLI
- Generates Metadata: Creates publication records for auditing
- Reports Results: Returns publication status with paths and checksums
Usage
Basic Usage (Local Target)
python skills/plugin.publish/plugin_publish.py dist/betty-framework-1.0.0.tar.gz
Publishes with defaults:
- Target:
local(dist/published/) - Checksum validation: Auto-detected from manifest.json
Via Betty CLI
/plugin/publish dist/betty-framework-1.0.0.tar.gz
Publish to Specific Target
# Publish to local directory
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=local
# Publish to Claude Marketplace (simulated)
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=marketplace
# Prepare GitHub Release (files only, manual creation needed)
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=gh-release
# Create GitHub Release automatically using gh CLI
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=gh-release \
--auto-create
Dry Run and Validation Modes
# Dry run - show what would happen without making changes
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=marketplace \
--dry-run
# Validate only - check checksums without publishing
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--validate-only
# Dry run with GitHub Release
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=gh-release \
--auto-create \
--dry-run
With Explicit Checksum Validation
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=local \
--sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
With Custom Manifest Path
python skills/plugin.publish/plugin_publish.py \
/tmp/betty-framework-1.0.0.tar.gz \
--target=release \
--manifest=/tmp/manifest.json
With Custom Marketplace Endpoint
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=marketplace \
--endpoint=https://api.example.com/plugins/upload
Command-Line Arguments
| Argument | Type | Default | Description |
|---|---|---|---|
package_path |
Positional | Required | Path to the .tar.gz package file |
--target |
Option | local |
Publication target: local, marketplace, or gh-release |
--sha256 |
Option | Auto-detect | Expected SHA256 checksum for validation |
--manifest |
Option | Auto-detect | Path to manifest.json |
--endpoint |
Option | Claude Marketplace | Marketplace API endpoint URL (for marketplace target) |
--dry-run |
Flag | False | Show what would be done without making changes |
--validate-only |
Flag | False | Only validate checksums without publishing |
--auto-create |
Flag | False | Automatically create GitHub Release using gh CLI (for gh-release target) |
Publication Targets
Local Target
Purpose: Copy package to local published directory for testing, archival, or internal distribution.
Output Location: dist/published/
Generated Files:
{package-name}.tar.gz- Copied package file{package-name}.tar.gz.publish.json- Publication metadata
Use Cases:
- Local testing before remote publication
- Internal company archives
- Offline distribution
- Backup copies
Example:
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=local
Output:
dist/published/
├── betty-framework-1.0.0.tar.gz
└── betty-framework-1.0.0.tar.gz.publish.json
Marketplace Target
Purpose: Upload plugin metadata to Claude Marketplace API endpoint (currently simulated).
Output Location: dist/published/marketplace/
Generated Files:
{package-name}.tar.gz.marketplace-publish.json- Simulation log with request/response
Use Cases:
- Publish to Claude Code Marketplace
- Upload to custom plugin repository
- Submit to enterprise plugin registry
Current Implementation: SIMULATED
- Generates complete HTTP POST request with JSON metadata
- Returns mock successful response
- No actual network request made
- Ready for real implementation (add requests library)
Example:
# Standard marketplace publication (simulated)
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=marketplace
# With custom endpoint
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=marketplace \
--endpoint=https://marketplace.claude.ai/api/v1/plugins
# Dry run first to see what would happen
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=marketplace \
--dry-run
JSON Metadata Structure:
{
"plugin": {
"name": "betty-framework",
"version": "1.0.0",
"description": "...",
"author": { ... },
"license": "MIT",
"homepage": "...",
"repository": "...",
"tags": [...],
"betty_version": ">=0.1.0"
},
"package": {
"filename": "betty-framework-1.0.0.tar.gz",
"size_bytes": 524288,
"checksums": {
"md5": "...",
"sha256": "..."
}
},
"submitted_at": "2025-10-24T12:00:00.000000+00:00"
}
GitHub Release Target
Purpose: Create GitHub Releases with auto-generated release notes and automatic upload support.
Output Location: dist/published/releases/
Generated Files:
{package-name}.tar.gz- Copied package fileRELEASE_NOTES_v{version}.md- Auto-generated release notes{package-name}.tar.gz.release.json- Release metadata
Use Cases:
- GitHub Releases publication (manual or automatic)
- Public open-source distribution
- Versioned releases with auto-generated notes
- Official product releases
Modes:
- Preparation Only (default): Prepares files for manual release creation
- Automatic Creation (
--auto-create): Uses gh CLI to create release automatically
Examples:
# Prepare release files only (manual upload needed)
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=gh-release
# Automatically create GitHub Release using gh CLI
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=gh-release \
--auto-create
# Dry run to see what would be created
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=gh-release \
--auto-create \
--dry-run
Requirements for Auto-Create:
- GitHub CLI (
gh) must be installed - Must be authenticated:
gh auth login - Must have write access to repository
- Tag must not already exist
Output:
dist/published/releases/
├── betty-framework-1.0.0.tar.gz
├── RELEASE_NOTES_v1.0.0.md
└── betty-framework-1.0.0.tar.gz.release.json
Operating Modes
Dry Run Mode (--dry-run)
Purpose: Test publication without making any changes
Behavior:
- Validates package and checksums
- Shows all operations that would be performed
- Does NOT create files, directories, or network requests
- Does NOT create GitHub Releases
- Returns success if all validation passes
Use Cases:
- Test before actual publication
- Verify configuration is correct
- Preview what will happen
- CI/CD validation steps
Example:
# Test local publication
python skills/plugin.publish/plugin_publish.py \
dist/betty-1.0.0.tar.gz \
--target=local \
--dry-run
# Test marketplace publication
python skills/plugin.publish/plugin_publish.py \
dist/betty-1.0.0.tar.gz \
--target=marketplace \
--dry-run
# Test GitHub Release creation
python skills/plugin.publish/plugin_publish.py \
dist/betty-1.0.0.tar.gz \
--target=gh-release \
--auto-create \
--dry-run
Output Example:
🔍 DRY RUN MODE - No changes will be made
📦 Publishing to local directory...
Would create directory: /home/user/betty/dist/published
Would copy: /home/user/betty/dist/betty-1.0.0.tar.gz
To: /home/user/betty/dist/published/betty-1.0.0.tar.gz
Would write metadata to: /home/user/betty/dist/published/betty-1.0.0.tar.gz.publish.json
✅ Dry run completed successfully
Validate Only Mode (--validate-only)
Purpose: Validate package integrity without publishing
Behavior:
- Validates package file exists
- Calculates MD5 and SHA256 checksums
- Compares against expected checksums from manifest.json
- Exits immediately after validation
- Does NOT publish to any target
Use Cases:
- Verify package integrity before distribution
- CI/CD checksum validation
- Security audits
- Package verification after download
Example:
# Validate package checksums
python skills/plugin.publish/plugin_publish.py \
dist/betty-1.0.0.tar.gz \
--validate-only
Output Example:
🔍 VALIDATE ONLY MODE ENABLED
📦 Package: dist/betty-1.0.0.tar.gz
🎯 Target: local
📄 Manifest: dist/manifest.json
🔍 Validating package checksums...
🔐 Calculating checksums...
MD5: d41d8cd98f00b204e9800998ecf8427e
SHA256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
✅ SHA256 checksum validation: PASSED
================================================================================
✅ VALIDATION SUCCESSFUL
================================================================================
Package is valid and ready for publication.
To publish, run without --validate-only flag:
python skills/plugin.publish/plugin_publish.py dist/betty-1.0.0.tar.gz --target=local
Note: --validate-only takes precedence over --dry-run if both are specified.
Output Files
Publication Metadata (Local Target)
File: {package-name}.tar.gz.publish.json
Structure:
{
"published_at": "2025-10-24T12:00:00.000000+00:00",
"target": "local",
"package": {
"filename": "betty-framework-1.0.0.tar.gz",
"path": "/home/user/betty/dist/published/betty-framework-1.0.0.tar.gz",
"size_bytes": 524288,
"checksums": {
"md5": "d41d8cd98f00b204e9800998ecf8427e",
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
}
},
"metadata": {
"name": "betty-framework",
"version": "1.0.0",
"description": "Betty Framework is RiskExec's system...",
"author": {
"name": "RiskExec",
"email": "platform@riskexec.com"
},
"license": "MIT"
}
}
Marketplace Publication Simulation Log
File: {package-name}.tar.gz.marketplace-publish.json
Structure:
{
"simulated_at": "2025-10-24T12:00:00.000000+00:00",
"target": "marketplace",
"endpoint": "https://marketplace.claude.ai/api/v1/plugins",
"request": {
"method": "POST",
"url": "https://marketplace.claude.ai/api/v1/plugins",
"headers": {
"Content-Type": "application/json",
"X-Plugin-Name": "betty-framework",
"X-Plugin-Version": "1.0.0",
"X-Package-SHA256": "..."
},
"json": {
"plugin": { ... },
"package": { ... },
"submitted_at": "..."
}
},
"response": {
"status": 200,
"body": {
"success": true,
"message": "Plugin published successfully",
"plugin": {
"id": "betty-framework-1.0.0",
"name": "betty-framework",
"version": "1.0.0",
"published_at": "2025-10-24T12:00:00.000000+00:00",
"download_url": "...",
"listing_url": "https://marketplace.claude.ai/plugins/betty-framework"
},
"checksums": { ... }
}
},
"dry_run": false,
"note": "This is a simulated request. No actual HTTP request was made. To enable real publication, add requests library implementation."
}
GitHub Release Notes
File: RELEASE_NOTES_v{version}.md
Auto-generated Content:
# betty-framework v1.0.0
## Release Information
- **Version:** 1.0.0
- **Released:** 2025-10-24
- **Package:** `betty-framework-1.0.0.tar.gz`
## Checksums
Verify the integrity of your download:
MD5: d41d8cd98f00b204e9800998ecf8427e SHA256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
## Installation
1. Download the package: `betty-framework-1.0.0.tar.gz`
2. Verify checksums (see above)
3. Extract: `tar -xzf betty-framework-1.0.0.tar.gz`
4. Install dependencies: `pip install -r requirements.txt`
5. Run: Follow instructions in README.md
## Description
Betty Framework is RiskExec's system for structured, auditable AI-assisted engineering...
## GitHub CLI Commands
To create this release using GitHub CLI:
```bash
# Create release
gh release create v1.0.0 \
--title "betty-framework v1.0.0" \
--notes-file RELEASE_NOTES.md \
betty-framework-1.0.0.tar.gz
Manual Upload
- Go to: https://github.com/YOUR_ORG/YOUR_REPO/releases/new
- Tag version:
v1.0.0 - Release title:
betty-framework v1.0.0 - Upload:
betty-framework-1.0.0.tar.gz - Add checksums to release notes
- Publish release
### Release Metadata
**File**: `{package-name}.tar.gz.release.json`
**Structure**:
```json
{
"prepared_at": "2025-10-24T12:00:00.000000+00:00",
"target": "gh-release",
"version": "1.0.0",
"name": "betty-framework",
"package": {
"filename": "betty-framework-1.0.0.tar.gz",
"path": "/home/user/betty/dist/published/releases/betty-framework-1.0.0.tar.gz",
"size_bytes": 524288,
"checksums": {
"md5": "...",
"sha256": "..."
}
},
"release_notes_path": "/home/user/betty/dist/published/releases/RELEASE_NOTES_v1.0.0.md",
"github_cli_command": "gh release create v1.0.0 --title \"betty-framework v1.0.0\" --notes-file ...",
"metadata": {
"name": "betty-framework",
"version": "1.0.0",
"description": "...",
"author": { ... },
"license": "MIT"
},
"dry_run": false,
"auto_created": true,
"github_release_url": "https://github.com/user/repo/releases/tag/v1.0.0"
}
Note: The auto_created field is true if --auto-create was used and succeeded, and github_release_url will contain the actual release URL.
Checksum Validation
Automatic Validation
By default, plugin.publish automatically detects and validates checksums from manifest.json:
python skills/plugin.publish/plugin_publish.py dist/betty-framework-1.0.0.tar.gz
Process:
- Looks for
dist/manifest.json - Extracts
package.checksums.sha256 - Calculates actual SHA256 of package file
- Compares and validates
Manual Validation
Explicitly provide expected SHA256:
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Validation Output
Success:
🔍 Validating package checksums...
🔐 Calculating checksums...
MD5: d41d8cd98f00b204e9800998ecf8427e
SHA256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
✅ SHA256 checksum validation: PASSED
Failure:
🔍 Validating package checksums...
🔐 Calculating checksums...
MD5: d41d8cd98f00b204e9800998ecf8427e
SHA256: abc123...
❌ SHA256 checksum validation: FAILED
Expected: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Actual: abc123...
Workflow Integration
Complete Build and Publish Pipeline
# Step 1: Build plugin
python skills/plugin.build/plugin_build.py
# Step 2: Validate package integrity
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--validate-only
# Step 3: Dry run to test publication
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=local \
--dry-run
# Step 4: Publish to local for testing
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=local
# Step 5: Publish to Claude Marketplace (simulated)
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=marketplace
# Step 6: Create GitHub Release automatically
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=gh-release \
--auto-create
Safe Publication Workflow (Recommended)
# 1. Validate first
python skills/plugin.publish/plugin_publish.py \
dist/betty-1.0.0.tar.gz \
--validate-only
# 2. Dry run to preview
python skills/plugin.publish/plugin_publish.py \
dist/betty-1.0.0.tar.gz \
--target=marketplace \
--dry-run
# 3. Actual publication
python skills/plugin.publish/plugin_publish.py \
dist/betty-1.0.0.tar.gz \
--target=marketplace
Automated CI/CD Integration
# .github/workflows/publish.yml
name: Publish Plugin
on:
push:
tags:
- 'v*'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Build plugin
run: python skills/plugin.build/plugin_build.py
- name: Validate package
run: |
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-*.tar.gz \
--validate-only
- name: Publish to Claude Marketplace
run: |
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-*.tar.gz \
--target=marketplace
- name: Create GitHub Release
env:
GH_TOKEN: ${{ github.token }}
run: |
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-*.tar.gz \
--target=gh-release \
--auto-create
CI/CD with Dry Run Testing
# .github/workflows/test-publish.yml
name: Test Publication
on:
pull_request:
branches: [main]
jobs:
test-publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build plugin
run: python skills/plugin.build/plugin_build.py
- name: Validate package
run: |
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-*.tar.gz \
--validate-only
- name: Test local publish (dry run)
run: |
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-*.tar.gz \
--target=local \
--dry-run
- name: Test marketplace publish (dry run)
run: |
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-*.tar.gz \
--target=marketplace \
--dry-run
- name: Test GitHub Release (dry run)
run: |
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-*.tar.gz \
--target=gh-release \
--auto-create \
--dry-run
Error Handling
Package Not Found
❌ Package file not found: /path/to/missing.tar.gz
Solution: Verify package path and run plugin.build first.
Invalid Target
❌ Invalid target: prod. Must be one of: local, marketplace, gh-release
Solution: Use one of the valid target values: local, marketplace, or gh-release.
Checksum Validation Failed
❌ SHA256 checksum validation: FAILED
Solution: Package may be corrupted. Rebuild using plugin.build.
Manifest Not Found
⚠️ Manifest not found: /path/to/manifest.json
⚠️ No expected checksum provided - skipping validation
Solution: Provide --manifest path or place manifest.json in package directory.
Advanced Usage
Publishing to Multiple Targets
#!/bin/bash
PACKAGE="dist/betty-framework-1.0.0.tar.gz"
# Validate first
python skills/plugin.publish/plugin_publish.py "$PACKAGE" --validate-only
# Publish to all targets
python skills/plugin.publish/plugin_publish.py "$PACKAGE" --target=local
python skills/plugin.publish/plugin_publish.py "$PACKAGE" --target=marketplace
python skills/plugin.publish/plugin_publish.py "$PACKAGE" --target=gh-release --auto-create
echo "Published to all targets successfully!"
Custom Endpoint Configuration
# Development marketplace endpoint
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=marketplace \
--endpoint=https://dev.marketplace.claude.ai/api/v1/plugins
# Production marketplace endpoint
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--target=marketplace \
--endpoint=https://marketplace.claude.ai/api/v1/plugins
Safe Publication with Validation
#!/bin/bash
PACKAGE="dist/betty-framework-1.0.0.tar.gz"
# Step 1: Validate checksums
echo "Validating package..."
python skills/plugin.publish/plugin_publish.py "$PACKAGE" --validate-only || exit 1
# Step 2: Dry run for all targets
echo "Running dry runs..."
python skills/plugin.publish/plugin_publish.py "$PACKAGE" --target=local --dry-run || exit 1
python skills/plugin.publish/plugin_publish.py "$PACKAGE" --target=marketplace --dry-run || exit 1
python skills/plugin.publish/plugin_publish.py "$PACKAGE" --target=gh-release --auto-create --dry-run || exit 1
# Step 3: Actual publication
echo "Publishing..."
python skills/plugin.publish/plugin_publish.py "$PACKAGE" --target=local
python skills/plugin.publish/plugin_publish.py "$PACKAGE" --target=marketplace
python skills/plugin.publish/plugin_publish.py "$PACKAGE" --target=gh-release --auto-create
echo "All publications completed successfully!"
Verification After Publication
# Local verification
cd dist/published
sha256sum -c <<< "e3b0c44... betty-framework-1.0.0.tar.gz"
# Extract and inspect
tar -tzf betty-framework-1.0.0.tar.gz | head -20
# Validate manifest
cat betty-framework-1.0.0.tar.gz.publish.json | jq .
Dependencies
- Python: 3.11+
- Standard Library: os, sys, json, yaml, hashlib, shutil, pathlib, datetime
- Betty Modules: betty.config
- Future: requests (for actual remote publication)
Related Skills
- plugin.build: Build plugin packages before publishing
- plugin.sync: Synchronize plugin.yaml from skill registry
- registry.update: Update skill registry entries
- audit.log: Log publication events for governance
Security Considerations
Checksum Validation
Always validate SHA256 checksums before publication:
- Detects package corruption
- Prevents tampering
- Ensures integrity across distribution channels
Publication Tracking
All publications are logged with:
- Timestamp (UTC)
- Target destination
- Checksums
- Package metadata
This creates an audit trail for governance and compliance.
Remote Publication (When Implemented)
For actual remote publication:
- Use HTTPS endpoints only
- Authenticate with API tokens (not in source code)
- Verify TLS certificates
- Implement retry logic with exponential backoff
- Log all API responses
Troubleshooting
Issue: Checksum mismatch after build
Symptom: SHA256 validation fails immediately after building
Causes:
- Manifest.json not generated by plugin.build
- Package file modified after build
- Incorrect manifest path
Solution:
# Rebuild package
python skills/plugin.build/plugin_build.py
# Verify manifest exists
ls -la dist/manifest.json
# Publish with explicit manifest
python skills/plugin.publish/plugin_publish.py \
dist/betty-framework-1.0.0.tar.gz \
--manifest=dist/manifest.json
Issue: Marketplace publication not actually uploading
Symptom: No network error but file not on marketplace
Cause: Marketplace publication is currently SIMULATED
Solution: This is expected behavior. The simulation creates a complete request structure in:
dist/published/marketplace/{package}.marketplace-publish.json
For actual HTTP upload, add requests library implementation in publish_marketplace().
Issue: GitHub Release fails
Symptom: gh release create command fails
Causes:
- GitHub CLI not installed
- Not authenticated with GitHub
- Tag already exists
- No write access to repository
Solutions:
# Install GitHub CLI
# macOS: brew install gh
# Linux: sudo apt install gh
# Authenticate
gh auth login
# Check existing releases
gh release list
# Delete existing tag if needed
gh release delete v1.0.0
git push --delete origin v1.0.0
Best Practices
- Use validate-only first: Always run
--validate-onlybefore publishing to verify package integrity - Dry run before publishing: Use
--dry-runto test publication workflows without making changes - Test locally first: Publish to
--target=localbefore marketplace or GitHub Release - Review release notes: Check auto-generated notes in
dist/published/releases/RELEASE_NOTES_*.md - Keep publication metadata: Retain
.jsonfiles for audit trails and compliance - Use version tags consistently: Follow semantic versioning (e.g., v1.0.0 format)
- Automate via CI/CD: Use GitHub Actions for consistent, reproducible releases
- Verify gh CLI setup: Test
gh auth statusbefore using--auto-create - Backup published packages: Keep copies for disaster recovery
- Use safe publication workflow: Validate → Dry run → Local → Remote → Release
Future Enhancements
- Actual HTTP POST implementation for marketplace target (add requests library)
- Support for multiple marketplace endpoints (dev, staging, prod)
- Digital signature support for package verification (GPG signing)
- Publication rollback mechanism for failed releases
- Automatic changelog generation from git commits
- Publication analytics and download tracking
- Multi-target parallel publication (async)
- Package verification after publication (download and verify checksums)
- Support for pre-release and draft GitHub Releases
- Integration with artifact registries (JFrog, Nexus)
- Webhook notifications on successful publication
- Support for package mirroring across multiple registries
Generated by: Betty Framework Version: 0.1.0 Last Updated: 2025-10-24