diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index b5287b2..358b1cc 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -25,6 +25,16 @@ "author": { "name": "vnz" } + }, + { + "name": "dependabot", + "description": "Check for dependency updates using Dependabot CLI with auto-detection of package managers", + "version": "1.0.0", + "source": "./plugins/dependabot", + "category": "development", + "author": { + "name": "vnz" + } } ] } diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 81f46e8..b255928 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,10 +14,10 @@ jobs: name: Lint and validate runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install just - uses: extractions/setup-just@v2 + uses: extractions/setup-just@v3 - uses: j178/prek-action@v1 # Runs all hooks (equivalent to `just all`): diff --git a/plugins/dependabot/.claude-plugin/plugin.json b/plugins/dependabot/.claude-plugin/plugin.json new file mode 100644 index 0000000..065f782 --- /dev/null +++ b/plugins/dependabot/.claude-plugin/plugin.json @@ -0,0 +1,11 @@ +{ + "name": "dependabot", + "version": "1.0.0", + "description": "Check for dependency updates using Dependabot CLI with auto-detection of package managers", + "license": "MIT", + "author": { + "name": "vnz" + }, + "repository": "https://github.com/vnz/cc-plugins", + "keywords": ["dependabot", "dependencies", "security", "updates", "npm", "terraform", "github-actions"] +} diff --git a/plugins/dependabot/README.md b/plugins/dependabot/README.md new file mode 100644 index 0000000..de9a36f --- /dev/null +++ b/plugins/dependabot/README.md @@ -0,0 +1,94 @@ +# Dependabot Plugin + +Check for dependency updates across your project using the official [Dependabot CLI](https://github.com/dependabot/cli) with automatic ecosystem detection. + +## Prerequisites + +1. **Dependabot CLI** - Install from https://github.com/dependabot/cli +2. **GitHub CLI (gh)** - For authentication via `gh auth token` + +## Installation + +```bash +/plugin install dependabot@cc-plugins-vnz +``` + +## Usage + +### Scan All Ecosystems + +``` +use dependabot +``` + +Auto-detects all package managers in your repository and checks for updates. + +### Scan Specific Ecosystem + +``` +use dependabot for terraform +use dependabot for npm +use dependabot for github-actions +``` + +## Supported Ecosystems + +| Ecosystem | Trigger Aliases | Detection Files | +|-----------|-----------------|-----------------| +| GitHub Actions | `github-actions`, `actions`, `workflows` | `.github/workflows/*.yml` | +| Terraform | `terraform`, `tf` | `*.tf` | +| npm/yarn/pnpm | `npm`, `yarn`, `pnpm` | `package.json` | +| Go | `go`, `golang` | `go.mod` | +| Python | `python`, `pip`, `pipenv` | `requirements.txt`, `pyproject.toml`, `Pipfile`, `setup.py` | +| Ruby | `ruby`, `bundler`, `gems` | `Gemfile` | +| Rust | `rust`, `cargo` | `Cargo.toml` | +| Docker | `docker` | `Dockerfile`, `*.dockerfile`, `docker-compose.yml` | +| Maven | `maven`, `java` | `pom.xml` | +| Gradle | `gradle` | `build.gradle`, `build.gradle.kts` | +| Composer | `composer`, `php` | `composer.json` | +| NuGet | `nuget`, `dotnet`, `csharp` | `*.csproj`, `packages.config`, `*.fsproj` | +| Helm | `helm` | `Chart.yaml` | +| Pub (Dart) | `dart`, `flutter`, `pub` | `pubspec.yaml` | +| Swift | `swift` | `Package.swift` | +| Hex (Elixir) | `elixir`, `hex` | `mix.exs` | + +## Workflow + +1. **Prerequisites check** - Verifies `dependabot` and `gh` CLIs are installed +2. **Ecosystem detection** - Finds package managers based on config files +3. **Update scan** - Runs `dependabot update --local` for each ecosystem +4. **Results presentation** - Shows available updates in a table +5. **PR creation** (optional) - Offers to apply updates and open PR(s) + +## PR Strategy + +When updates are found, you'll be asked: +- **One PR per ecosystem** - Separate PRs for npm, terraform, etc. +- **Single combined PR** - All updates in one PR + +## Authentication + +The plugin uses `gh auth token` to obtain a GitHub access token. Ensure you're authenticated with the GitHub CLI: + +```bash +gh auth login +``` + +## How It Works + +The Dependabot CLI runs locally against your repository: + +```bash +# Dry-run mode (check for updates) +LOCAL_GITHUB_ACCESS_TOKEN=$(gh auth token) dependabot update --local . + +# Apply mode (modify files) +LOCAL_GITHUB_ACCESS_TOKEN=$(gh auth token) dependabot update +``` + +The `--local .` flag runs in dry-run mode, showing what would be updated without making changes. + +## Links + +- [Dependabot CLI Repository](https://github.com/dependabot/cli) +- [Dependabot Documentation](https://docs.github.com/en/code-security/dependabot) diff --git a/plugins/dependabot/skills/dependabot.md b/plugins/dependabot/skills/dependabot.md new file mode 100644 index 0000000..b4d0001 --- /dev/null +++ b/plugins/dependabot/skills/dependabot.md @@ -0,0 +1,199 @@ +--- +description: Check for dependency updates using Dependabot CLI. Trigger with "use dependabot" to scan all ecosystems or "use dependabot for " for a specific one (e.g., terraform, npm, github-actions). +--- + +# Dependabot Update Skill + +Scan for dependency updates using the official Dependabot CLI and optionally create PRs for found updates. + +## 1. Prerequisites Check + +Before running, verify the required tools are installed: + +```bash +# Check if dependabot CLI is installed +command -v dependabot || echo "NOT_FOUND" + +# Check if gh CLI is installed (needed for authentication) +command -v gh || echo "NOT_FOUND" +``` + +**If dependabot CLI is not found:** +- Inform the user: "The Dependabot CLI is not installed." +- Provide installation link: https://github.com/dependabot/cli +- Stop execution until the CLI is available. + +**If gh CLI is not found:** +- Inform the user: "The GitHub CLI (gh) is needed for authentication." +- Suggest installation via their package manager. + +## 2. Parse User Intent + +Analyze the user's trigger phrase: + +- **"use dependabot"** → Scan ALL detected ecosystems +- **"use dependabot for terraform"** → Scan only `terraform` ecosystem +- **"use dependabot for npm"** → Scan only `npm_and_yarn` ecosystem +- **"use dependabot for github-actions"** or **"use dependabot for actions"** → Scan only `github_actions` ecosystem + +Map common aliases to Dependabot CLI ecosystem values: +| User Says | CLI Ecosystem | +|-----------|---------------| +| npm, yarn, pnpm | `npm_and_yarn` | +| github-actions, actions, workflows | `github_actions` | +| terraform, tf | `terraform` | +| go, golang | `go_modules` | +| python, pip, pipenv | `pip` | +| ruby, bundler, gems | `bundler` | +| rust, cargo | `cargo` | +| docker | `docker` | +| maven, java | `maven` | +| gradle | `gradle` | +| composer, php | `composer` | +| nuget, dotnet, csharp | `nuget` | +| helm | `helm` | +| dart, flutter, pub | `pub` | +| swift | `swift` | +| elixir, hex | `hex` | + +## 3. Ecosystem Auto-Detection + +If scanning all ecosystems, detect which are present using file existence checks: + +| Ecosystem | CLI Value | Detection Method | +|-----------|-----------|------------------| +| GitHub Actions | `github_actions` | Glob: `.github/workflows/*.yml` or `.github/workflows/*.yaml` | +| Terraform | `terraform` | Glob: `*.tf` or `**/*.tf` (check root and subdirs) | +| npm/yarn/pnpm | `npm_and_yarn` | File exists: `package.json` | +| Go | `go_modules` | File exists: `go.mod` | +| Python (pip) | `pip` | File exists: `requirements.txt`, `pyproject.toml`, `Pipfile`, or `setup.py` | +| Ruby | `bundler` | File exists: `Gemfile` | +| Rust | `cargo` | File exists: `Cargo.toml` | +| Docker | `docker` | Glob: `Dockerfile` or `*.dockerfile` or `docker-compose.yml` | +| Maven | `maven` | File exists: `pom.xml` | +| Gradle | `gradle` | File exists: `build.gradle` or `build.gradle.kts` | +| Composer | `composer` | File exists: `composer.json` | +| NuGet | `nuget` | Glob: `*.csproj` or `packages.config` or `*.fsproj` | +| Helm | `helm` | File exists: `Chart.yaml` | +| Pub (Dart) | `pub` | File exists: `pubspec.yaml` | +| Swift | `swift` | File exists: `Package.swift` | +| Hex (Elixir) | `hex` | File exists: `mix.exs` | + +Report detected ecosystems to the user before proceeding: +> "Detected ecosystems: npm_and_yarn, github_actions, terraform" + +If a specific ecosystem was requested but not detected: +> "The 'terraform' ecosystem was requested but no Terraform files were found in this repository." + +## 4. Run Dependabot Updates + +For each ecosystem to scan, run the Dependabot CLI in local mode: + +```bash +# Get the repository name dynamically +REPO=$(gh repo view --json owner,name --jq '.owner.login + "/" + .name') +LOCAL_GITHUB_ACCESS_TOKEN=$(gh auth token) dependabot update "$REPO" --local . +``` + +Where `` is the CLI ecosystem value (e.g., `npm_and_yarn`, `terraform`, `github_actions`). + +**Run ecosystems serially** (one at a time) to avoid output confusion. + +**Parse the output** for: +- Updated dependencies (look for table rows showing version changes) +- Security updates (vulnerabilities fixed) +- "No update needed" messages + +## 5. Present Results + +Summarize findings in a clear format: + +``` +## Dependabot Scan Results + +### npm_and_yarn +| Dependency | Current | Available | Type | +|------------|---------|-----------|------| +| lodash | 4.17.20 | 4.17.21 | security | +| express | 4.18.0 | 4.18.2 | update | + +### terraform +No updates available. + +### github_actions +| Action | Current | Available | Type | +|--------|---------|-----------|------| +| actions/checkout | v3 | v4 | update | +``` + +If no updates are found across all ecosystems: +> "All dependencies are up-to-date!" + +## 6. Offer PR Creation + +If updates were found, ask the user: + +> "Would you like to apply these updates and create a PR?" + +**If yes, ask about PR strategy:** + +> "How would you like to organize the updates?" +> 1. **One PR per ecosystem** - Separate PRs for npm, terraform, etc. +> 2. **Single combined PR** - All updates in one PR + +## 7. Apply Updates and Create PR(s) + +Based on user's choice: + +### For Each PR to Create: + +1. **Create a feature branch:** + ```bash + git checkout -b dependabot/-updates + # or for combined: dependabot/all-updates + ``` + +2. **Run dependabot update without --local** to apply changes: + ```bash + REPO=$(gh repo view --json owner,name --jq '.owner.login + "/" + .name') + LOCAL_GITHUB_ACCESS_TOKEN=$(gh auth token) dependabot update "$REPO" + ``` + Note: The non-local mode modifies files in place. + +3. **Stage and commit changes:** + ```bash + git add -A + git commit -m "chore(deps): update dependencies + + Updated by Dependabot CLI + + Co-Authored-By: Claude Opus 4.5 " + ``` + +4. **Push and create PR:** + ```bash + git push -u origin dependabot/-updates + gh pr create --title "chore(deps): update dependencies" \ + --body "## Summary + - Dependency updates detected by Dependabot CLI + + ## Updates + + + ## Test plan + - [ ] Verify build passes + - [ ] Verify tests pass + - [ ] Review changelog for breaking changes + + 🤖 Generated with [Claude Code](https://claude.ai/claude-code)" + ``` + +5. **Return to original branch** after PR creation. + +## Important Notes + +- Always use `gh auth token` for authentication - never ask for tokens directly +- The `--local .` flag runs in dry-run mode showing what would update +- Without `--local`, dependabot modifies files directly +- Some ecosystems may require additional configuration (e.g., private registries) +- If dependabot fails for an ecosystem, report the error and continue with others