diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 2693e9d..c79bd4f 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,7 +1,7 @@ ## Plugin Submission Checklist - [ ] Plugin ID follows format: `author.plugin-name` or lowercase-with-hyphens -- [ ] Manifest passes `npm run validate-plugins` (or `npm run validate-all`) +- [ ] Plugin JSON is valid (CI will validate automatically) - [ ] SHA256 checksum verified (if `distribution` with checksums is used) - [ ] Plugin tested locally - [ ] README / docs updated if adding new author or changing structure @@ -26,3 +26,5 @@ ## DCO By submitting this pull request, I certify that my contributions are made under the terms of the [Developer Certificate of Origin](https://developercertificate.org/). All commits are signed off with `git commit -s`. + +**Note:** DCO requires a valid email address that matches your Git commit author email. See [CONTRIBUTING.md](../CONTRIBUTING.md#developer-certificate-of-origin-dco) for details. diff --git a/.github/workflows/build-registry.yml b/.github/workflows/build-registry.yml new file mode 100644 index 0000000..b131a29 --- /dev/null +++ b/.github/workflows/build-registry.yml @@ -0,0 +1,92 @@ +name: Build Registry + +on: + push: + branches: + - main + paths: + - 'plugins/**' + - 'schemas/**' + paths-ignore: + - 'registry.json' + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + + - name: Install dependencies + run: | + npm install + + - name: Validate schema files + run: | + npm run validate-schemas + + - name: Validate individual plugin files + run: | + npm run validate-plugins + + - name: Build registry + run: | + npm run build + + - name: Validate registry + run: | + npm run validate + + - name: Validate repository URLs + run: | + node -e " + const fs = require('fs'); + const registry = JSON.parse(fs.readFileSync('registry.json', 'utf8')); + const https = require('https'); + const http = require('http'); + + async function checkUrl(url) { + return new Promise((resolve) => { + const client = url.startsWith('https') ? https : http; + const req = client.get(url, { timeout: 5000 }, (res) => { + resolve(res.statusCode === 200 || res.statusCode === 301 || res.statusCode === 302); + }); + req.on('error', () => resolve(false)); + req.on('timeout', () => { + req.destroy(); + resolve(false); + }); + }); + } + + (async () => { + for (const plugin of registry.plugins) { + if (plugin.repository) { + const valid = await checkUrl(plugin.repository); + if (!valid) { + console.warn('Warning: Repository URL may be invalid:', plugin.repository); + } + } + } + console.log('Repository URL validation complete'); + })(); + " + + - name: Commit registry.json + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + git add registry.json + if git diff --staged --quiet; then + echo "No changes to registry.json" + else + git commit -m "chore: update registry.json [skip ci]" + git push + fi diff --git a/.github/workflows/validate-manifest.yml b/.github/workflows/validate-manifest.yml index dcc30ff..e905ecf 100644 --- a/.github/workflows/validate-manifest.yml +++ b/.github/workflows/validate-manifest.yml @@ -39,8 +39,6 @@ jobs: - name: Check for duplicates run: npm run check-duplicates - - name: Build registry - run: npm run build - - - name: Validate registry - run: npm run validate + - name: Validate registry (if exists) + run: | + npm run validate || echo "⚠️ registry.json not found, skipping validation" diff --git a/.github/workflows/validate-registry.yml b/.github/workflows/validate-registry.yml index d3890c3..23d0cda 100644 --- a/.github/workflows/validate-registry.yml +++ b/.github/workflows/validate-registry.yml @@ -1,13 +1,6 @@ name: Validate Registry on: - push: - branches: - - main - paths: - - 'registry.json' - - 'plugins/**' - - 'schemas/**' pull_request: paths: - 'registry.json' @@ -38,45 +31,10 @@ jobs: run: | npm run validate-plugins - - name: Build registry - run: | - npm run build - - - name: Validate registry - run: | - npm run validate - - - name: Validate repository URLs + - name: Validate registry (if exists) run: | - node -e " - const fs = require('fs'); - const registry = JSON.parse(fs.readFileSync('registry.json', 'utf8')); - const https = require('https'); - const http = require('http'); - - async function checkUrl(url) { - return new Promise((resolve) => { - const client = url.startsWith('https') ? https : http; - const req = client.get(url, { timeout: 5000 }, (res) => { - resolve(res.statusCode === 200 || res.statusCode === 301 || res.statusCode === 302); - }); - req.on('error', () => resolve(false)); - req.on('timeout', () => { - req.destroy(); - resolve(false); - }); - }); - } - - (async () => { - for (const plugin of registry.plugins) { - if (plugin.repository) { - const valid = await checkUrl(plugin.repository); - if (!valid) { - console.warn('Warning: Repository URL may be invalid:', plugin.repository); - } - } - } - console.log('Repository URL validation complete'); - })(); - " + if [ -f registry.json ]; then + npm run validate + else + echo "⚠️ registry.json not found, skipping validation" + fi diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 31d9161..d463c85 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,88 +2,103 @@ Thank you for your interest in contributing to the Time Tracker Plugins Registry! +## Quick Summary + +Adding a plugin is simple: +1. **Fork** this repository +2. **Create** `plugins/{letter}/{author}/{plugin-id}/{version}/plugin.json` +3. **Submit** a Pull Request + +CI handles validation and registry building automatically. No local setup required (unless you want to use the interactive script). + +πŸ‘‰ **See [FAQ](#frequently-asked-questions-faq) below for common questions.** + ## Developer Certificate of Origin (DCO) -By contributing to this project, you agree to the [Developer Certificate of Origin](https://developercertificate.org/) (DCO). You must sign off your commits to certify that you have the right to submit your contribution. +**What is DCO?** +DCO is a simple way to certify that you have the right to submit your contribution. It's required for all contributions. -To sign off your commits, add the `-s` flag when committing: +**How to sign off:** +Just add `-s` flag when committing: ```bash git commit -s -m "Add plugin: your-plugin-name" ``` -This adds a line like the following to your commit message: +This automatically adds `Signed-off-by: Your Name ` to your commit. -``` -Signed-off-by: Your Name +**⚠️ Important:** +- All PRs are checked for DCO sign-off. Commits without sign-off will fail the DCO check. +- **Email is required**: DCO requires a valid email address in the format `Name `. The email must: + - Be a valid email format (you can't use just a username) + - Match your commit author email (the email Git uses when you commit) + +**Setting your Git email:** +If you haven't set your Git email, configure it first: +```bash +git config --global user.email "your.email@example.com" +git config --global user.name "Your Name" ``` -All pull requests are checked for DCO sign-off. Commits without sign-off will cause the DCO check to fail. +Then commit with `-s` flag as shown above. ## How to Add a Plugin -### Step 1: Prepare Your Plugin - -Before submitting your plugin to the registry, ensure: +### Prerequisites -1. **Your plugin follows the Plugin Template structure** - - See [Plugin Template](https://github.com/tmtrckr/plugin-template) for details - - Must have a `plugin.toml` manifest file - - Must be hosted on GitHub +Before adding your plugin, make sure: -2. **Your plugin has at least one release** - - Create a GitHub Release with version tag (e.g., `v1.0.0`) - - Release should include compiled binaries for supported platforms - - See Plugin Template for GitHub Actions workflow +βœ… Your plugin is hosted on GitHub +βœ… Your plugin repository has a `plugin.toml` manifest file +βœ… You have at least one GitHub Release with version tag (e.g., `v1.0.0`) +βœ… Your repository includes a README and license file -3. **Your plugin repository includes:** - - Clear README with installation instructions - - License file - - Plugin manifest (`plugin.toml`) +> πŸ’‘ **New to plugin development?** Check out the [Plugin Template](https://github.com/tmtrckr/plugin-template) for a complete example. -### Step 2: Fork the Repository +### Step 1: Fork and Clone -**Important**: Before creating a plugin entry, you must fork this repository: - -1. **Fork this repository** on GitHub -2. **Clone your fork** locally: +1. **Fork this repository** on GitHub (click the "Fork" button) +2. **Clone your fork**: ```bash git clone https://github.com/your-username/plugins-registry.git cd plugins-registry ``` -3. **Install dependencies**: - ```bash - npm install - ``` -### Step 3: Add Plugin Entry +> πŸ’‘ **Tip**: You only need `npm install` if you want to use the interactive script. For manual creation, you can skip it. -**Option A: Use the Interactive Script (Recommended)** +### Step 2: Create Plugin Entry -The easiest way to create a plugin entry is using the interactive script: +**Option A: Interactive Script (Easiest! 🎯)** ```bash +npm install npm run create-plugin ``` -This script will: -- Guide you through all required fields -- Automatically normalize your author name -- Create the correct directory structure -- Generate a properly formatted `plugin.json` file -- Validate the entry format +The script will: +- βœ… Ask you questions about your plugin +- βœ… Automatically normalize your author name +- βœ… Create the correct directory structure +- βœ… Generate a properly formatted `plugin.json` +- βœ… Validate everything for you **Option B: Manual Creation** -1. **Normalize author name**: lowercase, spaces β†’ hyphens, remove special characters (e.g. "John Doe" β†’ "john-doe"). The **first letter** of the normalized name is the partition (e.g. `j`). +If you prefer to create the entry manually: -2. **Create the versioned path**: - ```bash - mkdir -p plugins/j/john-doe/your-plugin-id/1.0.0 - ``` - Use your normalized author, plugin id, and version (semver). +**1. Normalize your author name:** +- Convert to lowercase +- Replace spaces with hyphens +- Remove special characters +- Example: "John Doe" β†’ "john-doe" +- First letter: `j` (this becomes the partition folder) + +**2. Create the directory structure:** +```bash +mkdir -p plugins/j/john-doe/your-plugin-id/1.0.0 +``` -3. **Create `plugin.json`** in that version directory (e.g. `plugins/j/john-doe/your-plugin-id/1.0.0/plugin.json`): +**3. Create `plugin.json`** in that directory: ```json { @@ -105,12 +120,13 @@ This script will: } ``` -**Important**: -- Path must be `plugins/{first-letter}/{normalized-author}/{plugin-id}/{version}/plugin.json` -- `id` must match the plugin directory name; `author` must normalize to the author directory name -- Version directory must be semver (e.g. `1.0.0`) +**⚠️ Important Rules:** +- Path format: `plugins/{first-letter}/{normalized-author}/{plugin-id}/{version}/plugin.json` +- `id` field must match the plugin directory name +- `author` field must normalize to the author directory name +- `latest_version` must match the version directory name -**Field Guidelines:** +**πŸ“– Field Descriptions:** - **id**: Lowercase, alphanumeric with hyphens only (e.g., `calendar-sync`, `jira-integration`) - **name**: Display name (max 100 characters) @@ -139,59 +155,27 @@ This script will: You can compute SHA256 locally with `sha256sum` (Linux/macOS) or `certutil -hashfile file.zip SHA256` (Windows). -### Step 4: Validate Your Entry +### Step 3: Quick Check Before Submitting -Before submitting, validate your entry: +Before creating your PR, verify: -1. **Check JSON syntax**: Ensure valid JSON -2. **Validate against schema**: Your entry must match `registry.schema.json` -3. **Verify ID matches directory**: The `id` field must match the plugin directory name -4. **Verify author matches directory**: The `author` field (when normalized) must match the author directory name -5. **Verify author is present**: The `author` field is required and cannot be empty -6. **Verify repository URL**: Ensure the GitHub repository exists and is accessible -7. **Check for duplicates**: Ensure no other plugin has the same `{author}/{id}` combination -8. **Validate your plugin**: Run `npm run validate-plugins` to check your plugin.json file - - CI will automatically build the registry and validate it when you submit a PR - - You can optionally run `npm run validate-all` for a full local check (includes building registry), but it's not required +βœ… `plugin.json` is valid JSON (no syntax errors) +βœ… All required fields are filled in +βœ… `id` matches your plugin directory name +βœ… `author` normalizes to your author directory name +βœ… Repository URL is correct and accessible -### Step 5: Install Git Hooks (Optional but Recommended) +> πŸ’‘ **Optional**: If you have Node.js, you can run `npm install && npm run validate-plugins` to check locally. But don't worry - CI will validate everything automatically when you submit your PR! -Install pre-commit hooks to automatically validate your changes before committing: +### Step 4: Submit Pull Request -```bash -npm run install-hooks -``` - -This will: -- Install a pre-commit hook that validates plugins before each commit -- Automatically build the registry when plugin files change -- Prevent invalid commits from being made - -### Step 6: Submit Pull Request - -1. **Validate your plugin:** - ```bash - npm run validate-plugins - ``` - - This checks your plugin.json file. CI will automatically: - - Validate schema files - - Validate all plugin files - - Build the registry from plugins - - Validate the built registry against the schema - - **Optional**: Run `npm run validate-all` for a full local check (builds and validates registry locally), but CI does this automatically. - -2. **Commit your changes** (with DCO sign-off): +1. **Commit your changes** (with DCO sign-off): ```bash git add plugins/{letter}/{normalized-author}/{plugin-id}/{version}/plugin.json git commit -s -m "Add plugin: your-plugin-name" ``` - **Important Notes:** - - **Do NOT commit `registry.json`** - CI will automatically regenerate it when your PR is merged - - The build script preserves timestamps when plugins haven't changed, so you won't see unnecessary diffs - - If you installed pre-commit hooks, validation will run automatically and will unstage `registry.json` if only the timestamp changed + **Important**: Do NOT commit `registry.json` - CI will automatically build and commit it after your PR is merged to main. 2. **Push to your fork:** ```bash @@ -204,7 +188,19 @@ This will: - Link to your plugin repository - Screenshots or demo (if applicable) -### Step 6: Review Process +### Step 5: What Happens Next + +**When you submit your PR:** +- βœ… CI automatically validates your plugin +- βœ… Maintainers review your submission +- βœ… Automated checks verify schema compliance and repository URLs + +**After your PR is merged:** +- βœ… CI automatically builds the registry +- βœ… Your plugin appears in `registry.json` +- βœ… Your plugin is available in the Time Tracker Marketplace! + +### Review Process - Registry maintainers will review your submission - Automated validation will check schema compliance @@ -214,12 +210,38 @@ This will: ## Updating an Existing Plugin -To update your plugin entry: +### Updating Plugin Metadata + +To update description, tags, or other metadata: + +1. Edit `plugin.json` in your existing version directory + - Example: `plugins/j/john-doe/jira-integration/1.0.0/plugin.json` +2. Commit and submit a PR -1. For **metadata changes** (description, tags, etc.): edit `plugin.json` in the version directory (e.g. `plugins/d/developer-name/example-plugin/1.0.0/plugin.json`). -2. For a **new version**: create a new version directory (e.g. `plugins/d/developer-name/example-plugin/1.1.0/`) and add a new `plugin.json` there. -3. Do not change the `author` field or move the plugin to a different author path without coordination. -4. Run `npm run validate-plugins` to check your plugin.json, then commit and submit a pull request. Do **not** commit `registry.json` (CI regenerates it automatically). +### Adding a New Version + +To add a new version of your plugin: + +1. Create a new version directory: + ```bash + mkdir -p plugins/j/john-doe/jira-integration/1.1.0 + ``` +2. Create `plugin.json` in the new version directory +3. Update `latest_version` in the new `plugin.json` to match the directory name +4. Commit and submit a PR + +**Example structure for multiple versions:** +``` +plugins/j/john-doe/jira-integration/ +β”œβ”€β”€ 1.0.0/ +β”‚ └── plugin.json +└── 1.1.0/ + └── plugin.json ← New version +``` + +**⚠️ Important:** +- Do NOT change the `author` field or move the plugin to a different author path +- Do NOT commit `registry.json` - CI handles this automatically ## Plugin Verification @@ -269,6 +291,65 @@ Choose the most appropriate category: - Include functionality keywords (e.g., `sync`, `export`, `automation`) - Use lowercase, avoid spaces +## Frequently Asked Questions (FAQ) + +### Do I need to install Node.js to add a plugin? + +**No!** You only need Node.js if you want to use the interactive `create-plugin` script. For manual creation, you can just create the files directly. + +### Do I need to build the registry locally? + +**No!** CI automatically builds `registry.json` after your PR is merged. Just create your `plugin.json` file and submit a PR. + +### What if I make a mistake in my plugin.json? + +Don't worry! CI will validate your plugin when you submit a PR and tell you what's wrong. You can fix it and update your PR. + +### Can I update my plugin later? + +Yes! You can: +- Update metadata by editing the existing `plugin.json` +- Add a new version by creating a new version directory + +### What if my author name has special characters? + +Special characters are removed during normalization. For example: +- "JosΓ© GarcΓ­a" β†’ "jose-garcia" +- "O'Brien" β†’ "obrien" +- "Smith & Co." β†’ "smith-co" + +### Can I have multiple versions of my plugin? + +Yes! Create separate version directories: +``` +plugins/j/john-doe/my-plugin/ +β”œβ”€β”€ 1.0.0/ +β”‚ └── plugin.json +└── 1.1.0/ + └── plugin.json +``` + +### Do I need to commit registry.json? + +**No!** Never commit `registry.json`. CI builds and commits it automatically after your PR is merged. + +### What email should I use for DCO sign-off? + +You can use any valid email address. The email in `Signed-off-by:` must: +- Be a valid email format (e.g., `user@example.com`) +- Match your Git commit author email + +**Common options:** +- Your GitHub email (if you have it public) +- Your personal email +- Any valid email address you control + +**Important:** You cannot use just a username - a valid email address is required. + +### How long does it take for my plugin to appear? + +After your PR is merged, CI automatically builds the registry (usually takes 1-2 minutes). Your plugin will then appear in `registry.json` and be available in the marketplace. + ## Questions? If you have questions about contributing: diff --git a/README.md b/README.md index 7a5fa01..bba18d0 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Community-driven registry for Time Tracker application plugins. This repository ## Statistics - **Total Plugins:** See [registry.json](registry.json) for current counts -- **Registry:** [registry.json](registry.json) is built from `plugins/` and validated in CI +- **Registry:** [registry.json](registry.json) is automatically built from `plugins/` by CI after PRs are merged ## Overview @@ -52,7 +52,7 @@ plugins/ - **Version** directory must be semver (e.g. `1.0.0`). Multiple versions per plugin are supported. - The `author` field in `plugin.json` is **required** and must normalize to the author directory name. -The `registry.json` file is built from these plugin files using `npm run build` (latest version per plugin is used). +The `registry.json` file is automatically built from these plugin files by CI (latest version per plugin is used). ### Plugin Metadata Schema @@ -77,47 +77,108 @@ Each plugin's `plugin.json` follows the schema defined in `schemas/manifest.sche ## Adding a Plugin -### Quick Start (Recommended) - -1. **Fork this repository** on GitHub -2. **Clone your fork** locally: - ```bash - git clone https://github.com/your-username/plugins-registry.git - cd plugins-registry - npm install - ``` -3. **Use the interactive script** to create a plugin entry: - ```bash - npm run create-plugin - ``` - This will guide you through all required fields and create the correct structure automatically. -4. **Validate your plugin**: - ```bash - npm run validate-plugins - ``` -5. **Commit and create a Pull Request** (see [CONTRIBUTING.md](CONTRIBUTING.md) for details) - - CI will automatically build and validate the registry when you submit a PR - -### Manual Process - -To add your plugin manually: - -1. **Fork this repository** -2. **Normalize author name**: lowercase, spaces β†’ hyphens, remove special characters (e.g. "John Doe" β†’ "john-doe") -3. **First letter**: use the first character of the normalized author (e.g. "john-doe" β†’ `j`) -4. **Create path**: `plugins/{first-letter}/{normalized-author}/{plugin-id}/{version}/` +### πŸš€ Quick Start (3 Simple Steps) + +**Step 1: Fork and Clone** +```bash +# 1. Fork this repository on GitHub (click "Fork" button) +# 2. Clone your fork: +git clone https://github.com/your-username/plugins-registry.git +cd plugins-registry +``` + +**Step 2: Create Plugin Entry** + +**Option A: Interactive Script (Easiest)** +```bash +npm install +npm run create-plugin +``` +The script will guide you through everything and create the correct structure automatically. + +**Option B: Manual Creation** +1. Create directory: `plugins/{first-letter}/{author}/{plugin-id}/{version}/` - Example: `plugins/j/john-doe/jira-integration/1.0.0/` -5. **Create `plugin.json`** in that version directory with your plugin metadata -6. **Ensure**: - - `id` matches the plugin directory name (e.g. `jira-integration`) - - `author` matches the author directory when normalized (e.g. "John Doe" β†’ "john-doe") - - `latest_version` or directory name is semver (e.g. `1.0.0`) -7. **Validate your plugin**: Run `npm run validate-plugins` to check your plugin.json -8. **Submit a pull request** (CI will automatically build and validate the registry) - -**Example**: Plugin "jira-integration" by "John Doe", version 1.0.0: -- Path: `plugins/j/john-doe/jira-integration/1.0.0/plugin.json` -- In `plugin.json`: `"id": "jira-integration"`, `"author": "John Doe"`, `"latest_version": "1.0.0"` +2. Create `plugin.json` file in that directory (see example below) + +**Step 3: Submit Pull Request** +```bash +git add plugins/j/john-doe/jira-integration/1.0.0/plugin.json +git commit -s -m "Add plugin: jira-integration" +git push origin main +# Then create a Pull Request on GitHub +``` + +That's it! CI will automatically validate your plugin and build the registry after your PR is merged. + +### πŸ“ Example: Adding "Jira Integration" Plugin + +**Author:** John Doe +**Plugin ID:** jira-integration +**Version:** 1.0.0 + +**1. Create the directory:** +```bash +mkdir -p plugins/j/john-doe/jira-integration/1.0.0 +``` + +**2. Create `plugins/j/john-doe/jira-integration/1.0.0/plugin.json`:** +```json +{ + "$schema": "https://github.com/tmtrckr/plugins-registry/schemas/manifest.schema.json", + "id": "jira-integration", + "name": "Jira Integration", + "author": "John Doe", + "repository": "https://github.com/johndoe/jira-integration", + "latest_version": "1.0.0", + "description": "Sync time entries with Jira tickets", + "category": "integration", + "verified": false, + "downloads": 0, + "tags": ["jira", "sync", "integration"], + "license": "MIT", + "min_core_version": "0.3.0", + "max_core_version": "1.0.0", + "api_version": "1.0" +} +``` + +**3. Commit and create PR:** +```bash +git add plugins/j/john-doe/jira-integration/1.0.0/plugin.json +git commit -s -m "Add plugin: jira-integration" +git push +``` + +### πŸ“‹ Understanding the Path Structure + +The path follows this pattern: `plugins/{first-letter}/{author}/{plugin-id}/{version}/` + +**Visual Example:** +``` +plugins/ +└── j/ ← First letter of "john-doe" + └── john-doe/ ← Normalized author name + └── jira-integration/ ← Plugin ID + └── 1.0.0/ ← Version + └── plugin.json ← Your plugin file +``` + +**How to determine each part:** + +| Part | How to Get It | Example | +|------|---------------|---------| +| **First letter** | First character of normalized author | "John Doe" β†’ "john-doe" β†’ `j` | +| **Author** | Normalize: lowercase, spacesβ†’hyphens | "John Doe" β†’ `john-doe` | +| **Plugin ID** | Your plugin identifier (lowercase, hyphens) | `jira-integration` | +| **Version** | Semantic version number | `1.0.0` | + +**⚠️ Important rules:** +- `id` in `plugin.json` must match the plugin directory name +- `author` in `plugin.json` must normalize to the author directory name +- `latest_version` must match the version directory name + +> πŸ’‘ **Need help?** See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed instructions and FAQ. ### Plugin Requirements @@ -199,7 +260,7 @@ The Time Tracker application discovers plugins through: ## Local Development -**Note**: This section covers commands for repository maintainers. Plugin contributors only need `npm run validate-plugins` to check their plugin.json - CI handles the rest automatically. +**Note**: This section covers commands for repository maintainers. Plugin contributors don't need to run any commands locally - CI handles validation and registry building automatically. ### Setup @@ -231,7 +292,7 @@ npm run build ### Validation -**For plugin contributors**: Run `npm run validate-plugins` to check your plugin.json file. CI will handle building and validating the registry automatically. +**For plugin contributors**: CI automatically validates your plugin.json when you submit a PR. No local validation is required. **For repository maintainers**: Full validation commands: @@ -251,13 +312,13 @@ Validate the aggregated registry (requires registry.json to exist - run `npm run npm run validate ``` -Validate everything (schemas, plugins, build registry, and validate registry): +Validate existing files (schemas, plugins, and registry.json if present): ```bash -npm run validate-all +npm run validate-files ``` -This runs: `validate-schemas` β†’ `validate-plugins` β†’ `build` β†’ `validate` +This runs: `validate-schemas` β†’ `validate-plugins` β†’ `validate` (skips registry validation if registry.json doesn't exist). Note: This does not build the registry - run `npm run build` first if you need to generate registry.json. Check for duplicate plugin IDs: @@ -271,7 +332,7 @@ Format the registry (sorts plugins and updates timestamp): npm run format ``` -### Git Hooks +### Git Hooks (Optional) Install pre-commit hooks to automatically validate plugins before committing: @@ -279,10 +340,7 @@ Install pre-commit hooks to automatically validate plugins before committing: npm run install-hooks ``` -This will: -- Validate plugin files before each commit -- Automatically build the registry when plugin files change -- Prevent invalid commits from being made +This will validate plugin files before each commit. CI handles registry building automatically, so this is optional. ### Example Plugin Entry @@ -304,11 +362,11 @@ Contributions are welcome! Please: 2. Ensure all URLs are valid 3. Provide clear descriptions 4. Use appropriate categories and tags -5. Sign off commits (DCO): `git commit -s -m "message"` +5. Sign off commits (DCO): `git commit -s -m "message"` (requires valid email - see [CONTRIBUTING.md](CONTRIBUTING.md#developer-certificate-of-origin-dco)) ### Ways to Contribute -- **Add a Plugin**: Use `npm run create-plugin` or the [CLI](tools/cli) (`node tools/cli/src/index.js create`) or follow the [manual process](CONTRIBUTING.md) +- **Add a Plugin**: Use `npm run create-plugin` (after `npm install`) or follow the [manual process](CONTRIBUTING.md) - **Request a Plugin**: Create an [issue using the plugin submission template](.github/ISSUE_TEMPLATE/plugin_submission.yml) - **Report Issues**: Open an issue for [bugs](.github/ISSUE_TEMPLATE/bug_report.yml) or [features](.github/ISSUE_TEMPLATE/feature_request.yml) - **Improve Documentation**: Submit PRs to improve docs diff --git a/package.json b/package.json index 83485b8..23a198e 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "validate": "node scripts/validate.js", "validate-plugins": "node scripts/validate-plugins.js", "validate-schemas": "node scripts/validate-schemas.js", - "validate-all": "npm run validate-schemas && npm run validate-plugins && npm run build && npm run validate", + "validate-files": "npm run validate-schemas && npm run validate-plugins && npm run validate", "format": "node scripts/format.js", "check-duplicates": "node scripts/check-duplicates.js", "create-plugin": "node scripts/create-plugin.js", diff --git a/plugins/README.md b/plugins/README.md index 2b99ab3..5e43e8c 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -32,12 +32,25 @@ plugins/ ## Adding a Plugin -1. Normalize your author name and determine the first letter. -2. Create `plugins/{letter}/{normalized-author}/{plugin-id}/{version}/`. -3. Add `plugin.json` with `id`, `author`, `latest_version` (matching the version directory), and other required fields. -4. Validate your plugin: Run `npm run validate-plugins` from the repository root. - - CI will automatically build and validate the registry when you submit a PR +**Quick steps:** +1. Normalize your author name (lowercase, spaces β†’ hyphens) +2. Create directory: `plugins/{first-letter}/{normalized-author}/{plugin-id}/{version}/` +3. Add `plugin.json` file with required fields +4. Submit a pull request + +**Example:** +- Author: "John Doe" β†’ normalized: "john-doe" β†’ first letter: `j` +- Plugin ID: `jira-integration` +- Version: `1.0.0` +- Path: `plugins/j/john-doe/jira-integration/1.0.0/plugin.json` + +**Important:** +- `id` in `plugin.json` must match the plugin directory name +- `author` in `plugin.json` must normalize to the author directory name +- `latest_version` must match the version directory name + +πŸ‘‰ **For detailed instructions and examples, see [CONTRIBUTING.md](../CONTRIBUTING.md)** ## Example -See `d/developer-name/example-plugin/1.0.0/plugin.json` for a full example. +See `d/developer-name/example-plugin/1.0.0/plugin.json` for a complete example. diff --git a/registry.json b/registry.json index f837bfd..079f68c 100644 --- a/registry.json +++ b/registry.json @@ -1,8 +1,29 @@ { "$schema": "https://github.com/tmtrckr/plugins-registry/schemas/registry.schema.json", "version": "1.0.0", - "last_updated": "2026-02-11T20:46:22.116Z", + "last_updated": "2026-02-13T20:55:37.494Z", "plugins": [ + { + "$schema": "https://github.com/tmtrckr/plugins-registry/schemas/manifest.schema.json", + "id": "billing", + "name": "Billing", + "author": "TimeTracker", + "repository": "https://github.com/tmtrckr/plugin-billing", + "latest_version": "1.0.0", + "description": "Billable time tracking plugin for Time Tracker application.", + "category": "other", + "verified": false, + "downloads": 0, + "tags": [], + "license": "MIT", + "min_core_version": "0.3.0", + "max_core_version": "1.0.0", + "api_version": "1.0", + "versions": [ + "1.0.0" + ], + "path": "plugins/t/timetracker/billing" + }, { "$schema": "https://github.com/tmtrckr/plugins-registry/schemas/manifest.schema.json", "id": "example-plugin", @@ -29,11 +50,82 @@ "1.0.0" ], "path": "plugins/d/developer-name/example-plugin" + }, + { + "$schema": "https://github.com/tmtrckr/plugins-registry/schemas/manifest.schema.json", + "id": "goals", + "name": "Goals", + "author": "TimeTracker", + "repository": "https://github.com/tmtrckr/plugin-goals", + "latest_version": "1.0.0", + "description": "Goal tracking plugin for Time Tracker application.", + "category": "productivity", + "verified": false, + "downloads": 0, + "tags": [ + "productivity" + ], + "license": "MIT", + "min_core_version": "0.3.0", + "max_core_version": "1.0.0", + "api_version": "1.0", + "versions": [ + "1.0.0" + ], + "path": "plugins/t/timetracker/goals" + }, + { + "$schema": "https://github.com/tmtrckr/plugins-registry/schemas/manifest.schema.json", + "id": "pomodoro-timer", + "name": "Pomodoro Timer", + "author": "TimeTracker", + "repository": "https://github.com/tmtrckr/plugin-pomodoro", + "latest_version": "1.0.0", + "description": "Pomodoro timer plugin for Time Tracker application", + "category": "productivity", + "verified": false, + "downloads": 0, + "tags": [ + "pomodoro" + ], + "license": "MIT", + "min_core_version": "0.3.0", + "max_core_version": "1.0.0", + "api_version": "1.0", + "versions": [ + "1.0.0" + ], + "path": "plugins/t/timetracker/pomodoro-timer" + }, + { + "$schema": "https://github.com/tmtrckr/plugins-registry/schemas/manifest.schema.json", + "id": "projects-tasks", + "name": "Projects & Tasks", + "author": "TimeTracker", + "repository": "https://github.com/tmtrckr/plugin-projects-tasks", + "latest_version": "1.0.0", + "description": "Project and task management plugin for Time Tracker application.", + "category": "reporting", + "verified": false, + "downloads": 0, + "tags": [ + "projects", + "tasks", + "reporting" + ], + "license": "MIT", + "min_core_version": "0.3.0", + "max_core_version": "1.0.0", + "api_version": "1.0", + "versions": [ + "1.0.0" + ], + "path": "plugins/t/timetracker/projects-tasks" } ], "statistics": { - "total_plugins": 1, - "total_versions": 1, - "total_authors": 1 + "total_plugins": 5, + "total_versions": 5, + "total_authors": 2 } } diff --git a/scripts/validate.js b/scripts/validate.js index 8f06a40..873cf6f 100644 --- a/scripts/validate.js +++ b/scripts/validate.js @@ -15,6 +15,12 @@ const registrySchemaPath = path.join(rootDir, 'schemas', 'registry.schema.json') const manifestSchemaPath = path.join(rootDir, 'schemas', 'manifest.schema.json'); try { + if (!fs.existsSync(registryPath)) { + console.log('⚠️ registry.json not found. Skipping registry validation.'); + console.log(' Run `npm run build` to generate registry.json first.'); + process.exit(0); + } + const registry = JSON.parse(fs.readFileSync(registryPath, 'utf8')); const registrySchema = JSON.parse(fs.readFileSync(registrySchemaPath, 'utf8')); const manifestSchema = JSON.parse(fs.readFileSync(manifestSchemaPath, 'utf8')); diff --git a/tools/cli/src/commands/create.js b/tools/cli/src/commands/create.js index 8c6e2ff..b5b7933 100644 --- a/tools/cli/src/commands/create.js +++ b/tools/cli/src/commands/create.js @@ -47,6 +47,6 @@ module.exports = async function create(args) { fs.mkdirSync(pluginDir, { recursive: true }); fs.writeFileSync(pluginPath, JSON.stringify(manifest, null, 2) + '\n', 'utf8'); console.log('Created:', pluginPath); - console.log('Next: npm run validate-all, then submit a PR.'); + console.log('Next: npm run validate-files, then submit a PR.'); return () => {}; };