Claude Code Plugins

Community-maintained marketplace

Feedback

Plugin Publish

@epieczko/betty
0
0

Publish bundled plugin packages to local, marketplace, or GitHub Releases with dry-run and validation modes

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

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

  1. Validates Package: Verifies the .tar.gz file exists and is readable
  2. Calculates Checksums: Computes MD5 and SHA256 hashes for integrity verification
  3. Validates SHA256: Compares against expected checksum from manifest.json
  4. Loads Metadata: Extracts plugin info from manifest.json (name, version, author, etc.)
  5. 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)
  6. 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
  7. Generates Metadata: Creates publication records for auditing
  8. 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 file
  • RELEASE_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:

  1. Preparation Only (default): Prepares files for manual release creation
  2. 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

  1. Go to: https://github.com/YOUR_ORG/YOUR_REPO/releases/new
  2. Tag version: v1.0.0
  3. Release title: betty-framework v1.0.0
  4. Upload: betty-framework-1.0.0.tar.gz
  5. Add checksums to release notes
  6. 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:

  1. Looks for dist/manifest.json
  2. Extracts package.checksums.sha256
  3. Calculates actual SHA256 of package file
  4. 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

  1. Use validate-only first: Always run --validate-only before publishing to verify package integrity
  2. Dry run before publishing: Use --dry-run to test publication workflows without making changes
  3. Test locally first: Publish to --target=local before marketplace or GitHub Release
  4. Review release notes: Check auto-generated notes in dist/published/releases/RELEASE_NOTES_*.md
  5. Keep publication metadata: Retain .json files for audit trails and compliance
  6. Use version tags consistently: Follow semantic versioning (e.g., v1.0.0 format)
  7. Automate via CI/CD: Use GitHub Actions for consistent, reproducible releases
  8. Verify gh CLI setup: Test gh auth status before using --auto-create
  9. Backup published packages: Keep copies for disaster recovery
  10. 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