From 11c125f5b244c27a32a641b232d7a66f476d0cc7 Mon Sep 17 00:00:00 2001 From: Nicholas Hart Date: Sat, 8 Aug 2026 11:33:58 -0700 Subject: [PATCH] chore: add CLAUDE.md, remove legacy release.yml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document the correct publish.yml + changesets + OIDC release flow in CLAUDE.md so it's clear to future Claude sessions. Remove release.yml which used NPM_TOKEN and GitHub Releases — superseded by Trusted Publishing via publish.yml. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/release.yml | 257 ---------------------------------- CLAUDE.md | 86 ++++++++++++ 2 files changed, 86 insertions(+), 257 deletions(-) delete mode 100644 .github/workflows/release.yml create mode 100644 CLAUDE.md diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 18e3684..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,257 +0,0 @@ -name: Release - -on: - release: - types: [published] - workflow_dispatch: # Manual trigger for testing - -permissions: - contents: write - id-token: write - -jobs: - publish-npm: - name: Publish to npm - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '20' - registry-url: 'https://registry.npmjs.org' - always-auth: true - - - name: Setup pnpm - uses: pnpm/action-setup@v3 - with: - version: 9 - run_install: false - - - name: Get pnpm store directory - id: pnpm-cache - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT - - - name: Cache pnpm store - uses: actions/cache@v4 - with: - path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm-store- - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Build packages - run: pnpm build - - - name: Publish to npm - run: pnpm changeset publish - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - - publish-vscode: - name: Publish VSCode Extension - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '20' - - - name: Setup pnpm - uses: pnpm/action-setup@v3 - with: - version: 9 - run_install: false - - - name: Get pnpm store directory - id: pnpm-cache - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT - - - name: Cache pnpm store - uses: actions/cache@v4 - with: - path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm-store- - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Build all packages - run: pnpm build - - - name: Package VSCode extension - run: | - cd packages/vscode - npx @vscode/vsce package --no-dependencies - - - name: Get extension version - id: version - run: | - VERSION=$(node -p "require('./packages/vscode/package.json').version") - echo "VERSION=$VERSION" >> $GITHUB_OUTPUT - - - name: Publish to VSCode Marketplace - run: | - cd packages/vscode - npx @vscode/vsce publish --packagePath md2do-vscode-${{ steps.version.outputs.VERSION }}.vsix - env: - VSCE_PAT: ${{ secrets.VSCE_PAT }} - - - name: Upload .vsix to GitHub Release - uses: softprops/action-gh-release@v1 - with: - files: packages/vscode/md2do-vscode-${{ steps.version.outputs.VERSION }}.vsix - tag_name: ${{ github.event.release.tag_name }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - publish-obsidian: - name: Publish Obsidian Plugin - runs-on: ubuntu-latest - steps: - - name: Checkout monorepo - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '20' - - - name: Setup pnpm - uses: pnpm/action-setup@v3 - with: - version: 9 - run_install: false - - - name: Get pnpm store directory - id: pnpm-cache - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT - - - name: Cache pnpm store - uses: actions/cache@v4 - with: - path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm-store- - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Build all packages - run: pnpm build - - - name: Get plugin version - id: version - run: | - VERSION=$(node -p "require('./packages/obsidian/manifest.json').version") - echo "VERSION=$VERSION" >> $GITHUB_OUTPUT - - - name: Checkout md2do-obsidian repo - uses: actions/checkout@v4 - with: - repository: TeamNickHart/md2do-obsidian - token: ${{ secrets.OBSIDIAN_REPO_TOKEN }} - path: md2do-obsidian - - - name: Copy built artifacts to obsidian repo - run: | - cp packages/obsidian/main.js md2do-obsidian/main.js - cp packages/obsidian/manifest.json md2do-obsidian/manifest.json - cp packages/obsidian/styles.css md2do-obsidian/styles.css - cp packages/obsidian/versions.json md2do-obsidian/versions.json - cp packages/obsidian/README.md md2do-obsidian/README.md - cp LICENSE md2do-obsidian/LICENSE - - - name: Commit and push to md2do-obsidian - run: | - cd md2do-obsidian - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - git add -A - git diff --cached --quiet && echo "No changes to commit" && exit 0 - git commit -m "Release v${{ steps.version.outputs.VERSION }}" - git push - - - name: Create GitHub release in md2do-obsidian - env: - GH_TOKEN: ${{ secrets.OBSIDIAN_REPO_TOKEN }} - run: | - cd md2do-obsidian - gh release create "${{ steps.version.outputs.VERSION }}" \ - --title "v${{ steps.version.outputs.VERSION }}" \ - --notes "Release v${{ steps.version.outputs.VERSION }} of md2do Obsidian plugin." \ - main.js manifest.json styles.css - - publish-openvsx: - name: Publish to Open VSX Registry - runs-on: ubuntu-latest - if: false # Disabled - OpenVSX not supported yet - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '20' - - - name: Setup pnpm - uses: pnpm/action-setup@v3 - with: - version: 9 - run_install: false - - - name: Get pnpm store directory - id: pnpm-cache - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT - - - name: Cache pnpm store - uses: actions/cache@v4 - with: - path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm-store- - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Build VSCode extension - run: pnpm --filter md2do-vscode build - - - name: Package VSCode extension - run: | - cd packages/vscode - npx @vscode/vsce package --no-dependencies - - - name: Get extension version - id: version - run: | - VERSION=$(node -p "require('./packages/vscode/package.json').version") - echo "VERSION=$VERSION" >> $GITHUB_OUTPUT - - - name: Publish to Open VSX Registry - run: | - cd packages/vscode - npx ovsx publish md2do-vscode-${{ steps.version.outputs.VERSION }}.vsix -p ${{ secrets.OPENVSX_TOKEN }} - continue-on-error: true diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..6e484a8 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,86 @@ +# md2do — Claude Instructions + +## Repository + +pnpm monorepo. Packages: `core`, `cli`, `config`, `todoist`, `mcp`, `vscode`, `obsidian`. + +``` +pnpm build # build all packages +pnpm -r run test:run # run all tests +pnpm lint # lint all packages +pnpm typecheck # typecheck all packages +``` + +## Release Process + +**The only correct release flow is via `publish.yml` + changesets. Do not create GitHub Releases manually.** + +### Steps + +1. **Include a changeset in every feature PR** that changes published packages: + + ```bash + pnpm changeset + # select affected packages, choose bump type, write summary + # commit the generated .changeset/*.md file with the PR + ``` + +2. **Merge the feature PR to main.** The `publish.yml` workflow runs automatically and opens a + "chore: version packages" PR with all version bumps and CHANGELOG entries applied. + +3. **Merge the version PR.** `publish.yml` detects no changeset files remain and runs: + ```bash + pnpm release # = pnpm build && changeset publish --provenance + ``` + Packages are published to npm via **OIDC Trusted Publishing** — no token required. + +### What NOT to do + +- **Do not** create GitHub Releases to trigger publishing — `release.yml` has been deleted. +- **Do not** use `NPM_TOKEN` — Trusted Publishing is configured on npmjs.com for all `@md2do/*` packages. +- **Do not** manually run `changeset version` or `changeset publish` locally unless debugging. +- **Do not** bump versions in `package.json` manually — changesets manages this. + +### Linked packages (always same version) + +`@md2do/cli`, `@md2do/core`, `@md2do/config`, `@md2do/todoist`, `@md2do/mcp` + +If changesets doesn't bump all of them (e.g. only touched packages move), manually align the +others to the same version and add a CHANGELOG entry: "Version bump to stay in sync with linked packages". + +### Independent versioning + +- `@md2do/vscode` — VSCode Marketplace, own version in `packages/vscode/package.json` +- `@md2do/obsidian` — GitHub releases in `TeamNickHart/md2do-obsidian`, own version in `packages/obsidian/manifest.json` + +These are **not** in the changesets linked group and don't publish to npm. + +## npm Trusted Publishing + +Configured on npmjs.com for each `@md2do/*` package: + +- Repository: `TeamNickHart/md2do` +- Workflow: `publish.yml` +- No `NPM_TOKEN` secret needed or used. + +## ESLint + +```bash +# Lint a specific package +npx eslint "packages//src/**/*.ts" + +# Lint all +pnpm lint +``` + +Test files (`**/tests/**/*.ts`) have `unsafe-*` and `unbound-method` rules relaxed — needed +for `vi.fn()` mock patterns. + +## Task Syntax + +- Priority: `!!!` = urgent, `!!` = high, `!` = normal, nothing = low +- Due date: `#due/YYYY-MM-DD` +- Completed: `{completed:YYYY-MM-DD}` +- Source links: `{slug:externalId}` (e.g. `{teams:msg-789}`, `{todoist:12345}`) +- Tags: `#tagname` (negative lookahead excludes `#due/`) +- Assignee: `@username`