Files
obsidian-mcp-server/docs/plans/2025-10-26-github-release-workflow-design.md

7.9 KiB

GitHub Release Workflow Design

Date: 2025-10-26 Status: Approved Author: William Ballou with Claude Code

Overview

This document describes the design for an automated GitHub Actions workflow that builds and releases the Obsidian MCP Server plugin when version tags are pushed to the repository.

Requirements

Functional Requirements

  • Trigger on semantic version tags (e.g., 1.0.0, 1.2.3)
  • Validate version consistency across package.json, manifest.json, and git tag
  • Run test suite and fail if tests don't pass
  • Build plugin using production build process
  • Create draft GitHub release with required Obsidian plugin files
  • Allow manual review and release note writing before publishing

Non-Functional Requirements

  • Simple, single-job architecture for easy debugging
  • Clear error messages when validation or tests fail
  • Deterministic builds using npm ci
  • Fast execution using GitHub Actions caching

Design Decisions

Automation Level: Semi-Automated

The workflow creates a draft release rather than auto-publishing. This provides:

  • Safety: Manual review before users can download
  • Quality: Time to write detailed release notes
  • Flexibility: Can delete and re-run if issues found
  • Control: Verify attached files are correct

Test Policy: Block on Failure

Tests must pass for release to proceed. This prevents:

  • Releasing broken code
  • Regressions reaching users
  • Build-time type errors in production

Trade-off: Urgent hotfixes require fixing or temporarily skipping failing tests.

Version Validation: Required

Workflow validates that version numbers match across:

  • Git tag (e.g., 1.2.3)
  • package.json version field
  • manifest.json version field

This catches common mistakes and ensures consistency required by Obsidian plugin spec.

Architecture: Single Job

All steps run sequentially in one job:

  1. Checkout code
  2. Validate versions
  3. Setup Node.js and dependencies
  4. Run tests
  5. Build plugin
  6. Create draft release

Rationale: Simpler than multi-job approach, easier to debug, acceptable runtime (~3-5 minutes).

Workflow Architecture

Trigger Pattern

on:
  push:
    tags:
      - "[0-9]+.[0-9]+.[0-9]+"

Matches semantic version tags without v prefix (per CLAUDE.md requirement).

Step 1: Version Validation

Purpose: Ensure tag, package.json, and manifest.json versions all match.

Implementation:

TAG_VERSION="${GITHUB_REF#refs/tags/}"
PKG_VERSION=$(node -p "require('./package.json').version")
MANIFEST_VERSION=$(node -p "require('./manifest.json').version")

if [ "$TAG_VERSION" != "$PKG_VERSION" ] || [ "$TAG_VERSION" != "$MANIFEST_VERSION" ]; then
  echo "❌ Version mismatch detected!"
  echo "Git tag: $TAG_VERSION"
  echo "package.json: $PKG_VERSION"
  echo "manifest.json: $MANIFEST_VERSION"
  exit 1
fi

Error cases:

  • Forgot to run npm version before tagging
  • Manually edited version in one file but not others
  • Typo in git tag name

Step 2: Dependency Setup

Node.js version: 18.x (LTS)

Installation: Use npm ci for:

  • Deterministic builds from package-lock.json
  • Faster than npm install
  • Catches lock file inconsistencies

Caching: GitHub Actions built-in npm cache:

- uses: actions/setup-node@v4
  with:
    node-version: '18'
    cache: 'npm'

Step 3: Test Execution

Command: npm test

Behavior:

  • Runs Jest test suite
  • Workflow fails if any test fails
  • Test output appears in Actions logs
  • No coverage report (development tool, not needed for releases)

Error handling:

  • Test failures → workflow stops, no release created
  • Clear error logs for debugging

Step 4: Build Process

Command: npm run build

What it does:

  1. Type checking: tsc -noEmit -skipLibCheck
  2. Bundling: node esbuild.config.mjs production
  3. Output: main.js in repository root

Validation: After build, verify these files exist:

  • main.js (build artifact)
  • manifest.json (repo file)
  • styles.css (repo file)

If any missing → workflow fails.

Step 5: Draft Release Creation

Tool: GitHub CLI (gh release create)

Command:

gh release create "$TAG_VERSION" \
  --title="$TAG_VERSION" \
  --draft \
  main.js \
  manifest.json \
  styles.css

Parameters:

  • Tag: Extracted from GITHUB_REF (e.g., 1.2.3)
  • Title: Same as tag version
  • --draft: Creates unpublished release
  • Files: Three required Obsidian plugin files

Authentication: Uses built-in GITHUB_TOKEN secret (no manual setup needed)

Developer Workflow

Creating a Release

Step 1: Update version

npm version patch  # or minor/major

This triggers version-bump.mjs which updates manifest.json and versions.json.

Step 2: Commit version bump

git commit -m "chore: bump version to X.Y.Z"

Step 3: Create and push tag

git tag X.Y.Z
git push && git push --tags

Step 4: Wait for GitHub Actions

  • Navigate to Actions tab
  • Watch workflow progress
  • Check for success or errors

Step 5: Review draft release

  • Navigate to Releases tab
  • Find draft release
  • Review attached files (download and verify if needed)

Step 6: Write release notes

  • Document what's new
  • Note breaking changes
  • List bug fixes
  • Credit contributors

Step 7: Publish release

  • Click "Publish release" button
  • Release becomes visible to users

Handling Failures

Version mismatch:

  • Fix version in mismatched file(s)
  • Commit fix
  • Delete incorrect tag: git tag -d X.Y.Z && git push origin :refs/tags/X.Y.Z
  • Recreate tag and push

Test failures:

  • Fix failing tests locally
  • Commit fixes
  • Delete tag and recreate (or create new patch version)

Build failures:

  • Check workflow logs for error
  • Fix build issue locally
  • Verify npm run build succeeds
  • Delete tag and recreate (or create new patch version)

Release creation failures:

  • Check if release already exists for tag
  • Delete existing release if needed
  • Re-run workflow or manually trigger

File Locations

  • Workflow file: .github/workflows/release.yml
  • Build output: main.js (root directory)
  • Required assets: manifest.json, styles.css (root directory)

Error Handling

Version Validation Errors

Detection: Before any build steps Message: Clear output showing all three versions Resolution: Fix mismatched files, delete/recreate tag

Test Failures

Detection: After dependencies installed Message: Jest output showing which tests failed Resolution: Fix tests, commit, delete/recreate tag

Build Failures

Detection: During build step Message: TypeScript or esbuild errors Resolution: Fix build errors locally, verify, delete/recreate tag

Missing Files

Detection: After build completes Message: Which required file is missing Resolution: Investigate why file wasn't created, fix, retry

Release Creation Failures

Detection: During gh CLI command Message: GitHub API error (e.g., release already exists) Resolution: Delete existing release or use different tag

Future Enhancements

Not Included in Initial Design

  • Automated release notes generation (manual preferred for quality)
  • Slack/Discord notifications on release
  • Automatic changelog updates
  • Release to Obsidian community plugin registry (separate process)
  • Build artifact signing/verification

These can be added later if needed.

Success Criteria

The workflow is successful if:

  1. Triggers only on semantic version tags
  2. Catches version mismatches before building
  3. Prevents releases with failing tests
  4. Produces correct build artifacts
  5. Creates draft releases with all required files
  6. Provides clear error messages on failures
  7. Completes in under 5 minutes for typical builds

References