Skip to content

Extension Patches: contribution workflow for community extensions #909

@stack72

Description

@stack72

Problem Statement

When a user pulls a community extension and finds it needs changes, there's no smooth path to contribute those changes back to the extension author. Today you'd need to:

  1. Find the author's source repo (if one exists — the repository manifest field is optional)
  2. Manually copy your changes into their repo structure
  3. Figure out the contribution process outside of swamp

This friction kills community contributions. The extension registry (swamp.club) is the only guaranteed connection point between contributor and maintainer, but it currently only supports one-way distribution (push/pull).

Proposed Solution

Three changes that create a complete contribution loop:

1. Pull extracts the manifest

Today extension pull extracts source files but not the manifest.yaml. If we include the manifest, then any pulled extension is immediately pushable. This is the foundation — without it, nothing else works.

After pull, the extension directory looks like:

extensions/models/aws-ec2/
├── manifest.yaml          ← new: extracted alongside source
├── instance.ts
└── _lib/
    └── helpers.ts

Changes needed:

  • Modify src/libswamp/extensions/pull.ts to extract manifest.yaml from the archive into the extension's source directory
  • Update upstream_extensions.json tracking to record that the manifest was extracted
  • Ensure extension push works correctly when pointed at a pulled extension's manifest

2. Extension patches via the CLI

New CLI commands that let contributors submit diffs and maintainers manage them.

Contributor workflow (User X):

# Pull the extension
swamp extension pull @Y/aws-ec2

# Edit the source files directly
vim extensions/models/aws-ec2/instance.ts

# Submit a patch — diffs local source against the pulled version
swamp extension patch @Y/aws-ec2 --message "Fix connection timeout when region is eu-west-1"

The patch command:

  • Diffs local source files against the version recorded in upstream_extensions.json
  • Uploads the diff + message to the registry, tagged with the contributor's identity from swamp auth
  • The maintainer gets notified

Maintainer workflow from CLI (User Y):

# See pending patches
swamp extension patches @Y/aws-ec2

# Output:
# PATCH-001  @X  "Fix connection timeout when region is eu-west-1"  (against v2026.03.15.1)
# PATCH-002  @Z  "Add support for arm64 instances"                  (against v2026.03.15.1)

# Review a patch
swamp extension patch view PATCH-001

# Pull their own extension if they don't have the source locally
swamp extension pull @Y/aws-ec2

# Apply the patch to local source
swamp extension patch apply PATCH-001

# Review, test, then push a new version
swamp extension push extensions/models/aws-ec2/manifest.yaml

Rejecting a patch:

swamp extension patch reject PATCH-001 --message "Thanks, but we handle this differently — see instance.ts:42"

New CLI commands:

Command Purpose
swamp extension patch @name --message "..." Submit a diff to the registry
swamp extension patches @name List pending patches
swamp extension patch view <patch-id> Review a patch diff
swamp extension patch apply <patch-id> Apply a diff to local source
swamp extension patch reject <patch-id> --message "..." Reject with reason

3. Accept patches directly on swamp.club

The registry already has everything it needs to publish a new version on the maintainer's behalf:

  • The current source (in the archive from the last push)
  • The diff (from the patch submission)
  • The manifest (bump the micro version automatically using CalVer)

Maintainer workflow from swamp.club (User Y):

  1. Gets a notification that a patch was submitted
  2. Opens the extension page on swamp.club — sees the patch with a rendered diff
  3. If the patch applies cleanly against the latest version, clicks "Accept"
  4. swamp.club applies the diff, rebundles, publishes a new version automatically
  5. Patch author is credited in the release notes
  6. Everyone with the extension installed sees the update on their next swamp extension update

If the patch is against an older version and conflicts with the latest, swamp.club shows "this patch conflicts with the current version" and the maintainer can ask the contributor to resubmit against the latest.

No CLI needed, no local checkout, no dev environment. Just review and accept in the browser.

New registry API surface:

Endpoint Method Purpose
/api/v1/extensions/:name/patches POST Submit a patch (diff + message + author identity)
/api/v1/extensions/:name/patches GET List pending patches for an extension
/api/v1/extensions/:name/patches/:id GET Get patch detail including rendered diff
/api/v1/extensions/:name/patches/:id PATCH Accept or reject (accept triggers rebuild + new version publish)

What this deliberately does NOT solve

  • Merge conflicts — if the patch doesn't apply cleanly against the latest version, the contributor is asked to rebase (pull latest, redo the change, resubmit). No automatic merge resolution.
  • Forking — if a contributor wants to publish their own version rather than contribute back, they change the collective in the manifest and push as @X/aws-ec2. This already works today with the manifest extraction change.
  • Discussion threads — patches have a message and an optional reject reason. For deeper conversation, the repository field in the manifest points to the right place.

Implementation Summary

Phase 1 — Foundation (CLI only):

  • Extract manifest on pull
  • swamp extension patch command to generate and submit diffs
  • swamp extension patches / patch view / patch apply / patch reject commands
  • Registry API endpoints for patch CRUD

Phase 2 — swamp.club UI:

  • Patch list view on extension detail page
  • Rendered diff viewer
  • Accept button that triggers server-side rebuild and version publish
  • Contributor notification on accept/reject

Affected components:

  • src/libswamp/extensions/pull.ts — manifest extraction
  • src/cli/commands/extension_patch.ts — new CLI commands (to be created)
  • src/libswamp/extensions/patch.ts — patch generation and application logic (to be created)
  • src/infrastructure/http/extension_api_client.ts — new API client methods for patch endpoints
  • src/infrastructure/persistence/upstream_extensions.ts — may need to track additional metadata for diffing
  • swamp.club backend — new API endpoints and rebuild pipeline
  • swamp.club frontend — patch UI on extension detail page

Alternatives Considered

  • Git-based fork/PR workflow: Requires the extension author to have a public repo and the contributor to use git. Too much friction and not all extensions have repos.
  • extension dev / extension fork commands: Overcomplicates what is essentially "edit files locally, submit a diff." No different from a git checkout conceptually.
  • Local overlay/patch system: Keeping upstream untouched with local overrides adds a layer of indirection that's harder to reason about and doesn't solve the contribution-back problem.

Metadata

Metadata

Assignees

Labels

featureFeature request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions