Files
opencode-obsidian/openspec/changes/archive/2026-02-14-setup-brat-packaging/design.md
2026-02-14 16:19:54 +01:00

6.2 KiB

Design: BRAT-compatible packaging and releases

Context

The obsidian-opencode plugin is currently in early development (v0.1.0). The repository contains main.js which is a build artifact, while styles.css is a static source file. Users must manually clone/build to install. This creates friction for beta testers and doesn't scale.

BRAT (Beta Reviewer's Auto-update Tool) is the community standard for beta plugin distribution. It works by monitoring GitHub releases and downloading manifest.json, main.js, and styles.css from release assets.

Current state:

  • Uses Bun as package manager and build tool
  • Has esbuild-based build system producing main.js
  • Has CI workflow for testing but no release automation
  • manifest.json exists but isn't synchronized with package.json
  • main.js build artifact is already in .gitignore

Goals / Non-Goals

Goals:

  • Enable one-click installation via BRAT for beta testers
  • Automate release creation on version tag push
  • Ensure manifest.json version always matches release tag
  • Remove build artifacts from git repository
  • Provide simple version bumping commands for developers

Non-Goals:

  • Marketplace submission (out of scope for this change)
  • Automated changelog generation
  • Multi-platform release assets (only JS/CSS files, no binaries)
  • Version pinning or rollback mechanisms
  • Signing or verification of releases

Decisions

1. Use bun pm version for version management

Rationale: Bun's built-in version manager updates package.json, creates a git commit, and tags automatically. This is simpler than custom scripts and matches the existing Bun-based toolchain.

Alternatives considered:

  • Custom Node.js script: More code to maintain, requires parsing JSON
  • standard-version or semantic-release: Too complex for early-stage project
  • Manual editing: Error-prone, inconsistent

2. Synchronized version updates: package.json + manifest.json

Approach: Use Bun's npm lifecycle scripts. When bun pm version runs, it executes the "version" script after updating package.json but before creating the commit. In this script, we read the new version from package.json and update manifest.json. Both files are then committed together with the same version.

Rationale: Keeps both files in sync at all times in the repository. The manifest.json always reflects the current package.json version, making it clear what version is being developed. This also simplifies the release workflow since manifest.json is already correct.

Implementation:

  1. Add a "version" script to package.json that runs a sync script
  2. The sync script reads package.json version and writes it to manifest.json
  3. Stage manifest.json with git add so it's included in the version commit
  4. bun pm version handles the commit and tag automatically

Alternatives considered:

  • Two-stage (release-time sync): Manifest in repo stays out of sync with package.json, confusing during development
  • Custom version script: Would lose Bun's built-in lifecycle management
  • Pre-commit hook: Would run on every commit, not just version bumps

3. Tag-triggered GitHub Actions workflow

Approach: Workflow triggers on v* tag push (e.g., v0.1.0). This is explicit and intentional - releases happen only when a developer decides to tag.

Rationale: Prevents accidental releases from every commit. Tag-based triggers are standard for GitHub releases and integrate well with bun pm version which creates tags.

Alternatives considered:

  • Manual workflow dispatch: More steps, easier to forget
  • Release on every push to main: Too frequent, no control
  • Release on merged PR: Good for continuous deployment, but we want explicit versioning

4. Mark all releases as prerelease: true during beta

Approach: The GitHub Actions workflow will always set prerelease: true on releases. This is hardcoded until we're ready for marketplace.

Rationale: Signals to users and BRAT that these are beta versions. Once we submit to marketplace, we'll change this to prerelease: false for stable releases.

Alternatives considered:

  • Detect from version string (e.g., -beta suffix): More complex, inconsistent with BRAT expectations
  • Manual toggle in workflow: Easy to forget

5. Build artifact (main.js) only in releases

Approach: main.js is already in .gitignore. The GitHub Actions workflow will build it and attach to releases. styles.css is a static source file and remains tracked in git.

Rationale: main.js is generated by esbuild and should not be in git. styles.css is hand-written and should be version controlled. Both are included in releases for BRAT distribution.

Trade-off: Repository won't have main.js after clone - developers must run bun install && bun run build. Acceptable since this is a development workflow.

Risks / Trade-offs

Risk Mitigation
Tag pushed but release fails Workflow will fail visibly; developer can delete tag and retry, or manually create release
Version mismatch between package.json and manifest.json in release Workflow enforces manifest.json version is updated from package.json before build
Users can't install from git clone anymore Document that BRAT is the intended install method for users; git clone is for developers only
Build fails on CI but works locally Existing CI already builds successfully; release workflow uses same build command
Forgetting to use bun pm version vs manual tag Document in CONTRIBUTING.md; consider adding a check that verifies tag matches package.json version

Migration Plan

  1. Prepare repository:

    • Verify main.js is in .gitignore (already done)
    • Keep styles.css tracked in git (it's a static source file)
  2. Add version scripts:

    • Add version:patch, version:minor, version:major to package.json scripts
  3. Create release workflow:

    • Add .github/workflows/release.yml
  4. Test release process:

    • Run bun run version:patch locally
    • Verify tag is created
    • Push tag and verify workflow creates release
    • Test installing via BRAT
  5. Update documentation:

    • Add BRAT installation section to README
    • Add release process to CONTRIBUTING.md

Open Questions

None at this time - design is ready for implementation.