# Contributing to @synity/bitrix-skill ## Dev Setup ```bash git clone https://github.com/synity-tech/bitrix-tools.git cd bitrix-tools pnpm install pnpm build pnpm test ``` ## Commit Format Use [Conventional Commits](https://www.conventionalcommits.org/) with a Bitrix task reference: ``` feat: add bx-task time-log subcommand [B24:1234] fix: handle missing TASK_ID in walk-up [B24:1234] chore: update dependencies [B24:1234] ``` The `[B24:NNNN]` tag is required — it enables the GitHub Action to sync the commit link into the Bitrix task chat. ## Branch Naming | Prefix | Use | |--------|-----| | `feat/` | New features | | `fix/` | Bug fixes | | `chore/` | Maintenance, deps, CI | | `docs/` | Documentation only | ## PR Requirements 1. **Changeset present** — run `pnpm changeset` and commit the generated file. - Skip only for `docs/` or `chore/ci` PRs that don't affect the published package. 2. **CI must pass** — typecheck + lint + tests. 3. **PR description** — fill in the template: summary, test plan, changeset checkbox. ## Adding a New Feature Each feature lives under `src/features//` and must include: ``` src/features// ├── feature.json — feature metadata (name, description, assets list) ├── install.ts — installer logic (extends BaseInstaller) └── assets/ — files that get written to the target project ``` ### `feature.json` schema ```json { "name": "my-feature", "description": "Short description", "version": "1.0.0", "assets": [ { "src": "assets/my-file.sh", "dest": ".claude/scripts/my-file.sh", "mode": "0755" } ], "requiredEnv": ["MY_ENV_VAR"], "docs": ["docs/feature-my-feature.md"] } ``` ### Installer contract ```typescript // src/features/my-feature/install.ts import { BaseInstaller } from '../../lib/base-installer.js'; export class MyFeatureInstaller extends BaseInstaller { async install(opts: InstallOptions): Promise { await this.copyAssets(opts); await this.mergeSettings(opts); } } ``` Register the feature in `src/features/index.ts`. ## Release Process Releases are fully automated by [Changesets](https://github.com/changesets/changesets) + GitHub Actions (`.github/workflows/release.yml`). The happy path needs **no manual `npm publish` and no OTP**. 1. **Add a changeset** with your change: ```bash pnpm changeset # pick the bump (patch/minor/major) + write a summary ``` Commit the generated `.changeset/*.md` and open your PR. 2. **Merge your PR** to `main`. The Changesets Action opens (or updates) a **"Version Packages"** PR that runs `changeset version` — bumping `package.json` and accumulating `CHANGELOG.md`. 3. **Merge the "Version Packages" PR.** That push to `main` runs `pnpm release` (`pnpm build && changeset publish`), authenticated via the `NPM_TOKEN` secret (`NODE_AUTH_TOKEN`). `prepublishOnly` (`lint:versions && build`) runs inside `changeset publish`. The new version is published to npm + a git tag is pushed. `changeset publish` is idempotent — it skips any version already on npm, so re-runs are safe. **Manual publish is a fallback only** (e.g. CI outage). It requires a 2FA OTP: ```bash pnpm changeset version # local bump pnpm changeset publish --otp ``` Prefer the CI flow — do not routinely publish by hand. ### The `NPM_TOKEN` secret (maintainers) CI authenticates publishes with the `NPM_TOKEN` GitHub repo secret. It **must** be a real npm token with **read-write** access to the `@synity` scope: - **Granular Access Token** — starts with **`npm_…`** (≈40 chars). On npmjs.com → *Access Tokens* → *Generate New Token* → *Granular*, give it **Read and write** on the `@synity` scope (or the `@synity/bitrix-skills` package). **Note the expiry** — granular tokens expire, and when they do CI publishes start failing. - **Classic Automation token** — UUID form `xxxxxxxx-…` (36 chars), no expiry, bypasses 2FA. Good for long-lived CI. Do **not** paste any other secret (a 64-hex API key, a GitHub token, etc.) — only an `npm_…` / UUID npm token works. Set/rotate it with: ```bash gh secret set NPM_TOKEN --repo synity-tech/bitrix-tools # paste the npm_… token ``` **Troubleshooting — publish fails with `E404 Not Found - PUT .../@synity%2fbitrix-skills`:** this is npm's way of reporting an **auth failure** on a write (it returns 404, not 403, to hide package existence). It means the token is **invalid, expired, or lacks publish rights** — not that the package is missing. Fix: mint a fresh `npm_…` token (read-write on `@synity`), `gh secret set NPM_TOKEN`, then re-run the failed release workflow (`gh run rerun `). `changeset publish` is idempotent, so re-running safely publishes the pending version.