OpenCode GitLab Plugin

A comprehensive GitLab API plugin for OpenCode that provides AI-powered access to GitLab's REST API. This plugin enables seamless interaction with merge requests, issues, pipelines, repositories, epics, and more through natural language commands.
π Table of Contents
β¨ Features
Core Capabilities
- π Merge Requests: Full CRUD operations, discussions, notes, changes, commits, and pipelines
- π Issues: Create, read, update, and comment on issues with advanced filtering
- π― Work Items: Unified interface for issues, epics, tasks, and other work tracking items
- π CI/CD Pipelines: Monitor, analyze, and retry pipeline jobs with detailed logs
- π¦ Repository Operations: File management, commits, branches, and tree navigation
- π Advanced Search: Multi-scope search across projects, code, issues, and merge requests
- π Epics: Enterprise-level epic management with issue associations
- β
TODOs: Personal task management and notifications
- π Security: Vulnerability scanning and security report access
- π Wiki: Wiki page content retrieval
- π₯ Project Management: Member management and project details
Technical Features
- TypeScript: Full type safety with comprehensive type definitions
- ESM Support: Modern ES modules for optimal tree-shaking
- Zod Validation: Runtime schema validation for all API inputs
- GraphQL Support: Native GraphQL API support with type-safe mutations and queries
- GID Validation: Automatic validation of GitLab Global IDs with descriptive error messages
- Error Handling: Robust error handling with detailed error messages
- Authentication: Multiple authentication methods (OAuth, API tokens)
- Rate Limiting: Built-in handling for GitLab API rate limits
- Caching: Efficient API response handling
- Modular Architecture: Clean separation of concerns with client and tool modules
- Comprehensive Testing: 142 tests with full coverage of all features
ποΈ Architecture
System Architecture
graph TB
subgraph "OpenCode Environment"
AI[AI Assistant]
Plugin[GitLab Plugin]
end
subgraph "Plugin Components"
Tools[Tool Definitions]
Client[GitLab API Client]
Auth[Authentication Manager]
Validator[Zod Schema Validator]
end
subgraph "GitLab API"
REST[REST API v4]
MR[Merge Requests]
Issues[Issues]
Pipelines[Pipelines]
Repos[Repositories]
Epics[Epics]
Security[Security]
end
AI -->|Natural Language| Plugin
Plugin --> Tools
Tools --> Validator
Validator --> Client
Client --> Auth
Auth --> REST
REST --> MR
REST --> Issues
REST --> Pipelines
REST --> Repos
REST --> Epics
REST --> Security
Plugin Structure
graph LR
subgraph "src/index.ts"
A[GitLabApiClient Class]
B[Authentication Functions]
C[Tool Definitions]
D[Plugin Export]
end
A --> A1[HTTP Methods]
A --> A2[Merge Request APIs]
A --> A3[Issue APIs]
A --> A4[Pipeline APIs]
A --> A5[Repository APIs]
A --> A6[Epic APIs]
A --> A7[Search APIs]
B --> B1[readTokenFromAuthStorage]
B --> B2[getGitLabClient]
C --> C1[60+ Tool Definitions]
D --> A
D --> B
D --> C
Authentication Flow
sequenceDiagram
participant User
participant Plugin
participant AuthManager
participant Storage
participant GitLab
User->>Plugin: Initialize Plugin
Plugin->>AuthManager: getGitLabClient()
AuthManager->>AuthManager: Check GITLAB_TOKEN env
alt Token in Environment
AuthManager->>GitLab: Use env token
else No env token
AuthManager->>Storage: Read ~/.local/share/opencode/auth.json
Storage->>AuthManager: Return token
AuthManager->>GitLab: Use stored token
end
GitLab->>Plugin: API Response
Plugin->>User: Tool Result
π¦ Installation
Prerequisites
- Node.js >= 18.0.0
- npm >= 9.0.0 or Bun
- GitLab account with API access
- GitLab Personal Access Token or OAuth token
Install from npm
npm install @gitlab/opencode-gitlab-plugin
bun add @gitlab/opencode-gitlab-plugin
yarn add @gitlab/opencode-gitlab-plugin
Install from GitLab Repository (Development)
npm install git+https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin.git
bun add git+https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin.git
Install Specific Version
npm install @gitlab/opencode-gitlab-plugin@1.0.0
npm install git+https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin.git
npm install git+https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin.git
Using package.json
Add to your package.json:
{
"dependencies": {
"@gitlab/opencode-gitlab-plugin": "^1.0.0"
}
}
Then run:
npm install
βοΈ Configuration
Environment Variables
export GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx
export GITLAB_INSTANCE_URL=https://gitlab.example.com
OpenCode Configuration
Add the following plugin to your opencode configuration ~/.config/opencode/opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["@gitlab/opencode-gitlab-plugin"]
}
Authentication Storage
The plugin supports reading tokens from OpenCode's auth storage:
Location: ~/.local/share/opencode/auth.json
Format:
{
"gitlab": {
"type": "oauth",
"access": "your-oauth-token"
}
}
Or for API tokens:
{
"gitlab": {
"type": "api",
"key": "glpat-xxxxxxxxxxxxxxxxxxxx"
}
}
Token Priority
GITLAB_TOKEN environment variable (highest priority)
- OpenCode auth storage (
~/.local/share/opencode/auth.json)
- Error if no token found
π οΈ Available Tools
The plugin provides 68+ tools organized into the following categories:
Merge Request Tools (13 tools)
graph LR
MR[Merge Requests] --> Get[gitlab_get_merge_request]
MR --> List[gitlab_list_merge_requests]
MR --> Create[gitlab_create_merge_request]
MR --> Update[gitlab_update_merge_request]
MR --> Changes[gitlab_get_mr_changes]
MR --> Discussions[gitlab_list_mr_discussions]
MR --> Notes[gitlab_list_mr_notes]
MR --> CreateNote[gitlab_create_mr_note]
MR --> Commits[gitlab_get_mr_commits]
MR --> Pipelines[gitlab_get_mr_pipelines]
gitlab_get_merge_request | Get details of a specific merge request |
gitlab_list_merge_requests | List merge requests with filtering |
gitlab_create_merge_request | Create a new merge request |
gitlab_update_merge_request | Update an existing merge request |
gitlab_get_mr_changes | Get file changes/diff for a merge request |
gitlab_list_mr_discussions | List discussion threads on a merge request |
gitlab_list_mr_notes | List all comments in flat structure |
gitlab_create_mr_note | Add a comment to a merge request |
gitlab_get_mr_commits | Get commits in a merge request |
gitlab_get_mr_pipelines | Get pipelines for a merge request |
Issue Tools (5 tools)
gitlab_create_issue | Create a new issue in a project |
gitlab_get_issue | Get details of a specific issue |
gitlab_list_issues | List issues with filtering |
gitlab_list_issue_notes | List all comments on an issue |
gitlab_create_issue_note | Add a comment to an issue |
Work Item Tools (7 tools)
gitlab_get_work_item | Get a single work item (issue, epic, task) |
gitlab_list_work_items | List work items in a project or group |
gitlab_get_work_item_notes | Get all comments for a work item |
gitlab_create_work_item | Create a new work item |
gitlab_update_work_item | Update an existing work item |
gitlab_create_work_item_note | Add a comment to a work item |
Pipeline Tools (6 tools)
gitlab_list_pipelines | List pipelines for a project |
gitlab_get_pipeline | Get details of a specific pipeline |
gitlab_list_pipeline_jobs | List jobs for a pipeline |
gitlab_get_job_log | Get log output of a CI job |
gitlab_retry_job | Retry a failed or canceled job |
gitlab_get_pipeline_failing_jobs | Get all failed jobs in a pipeline |
Repository Tools (9 tools)
gitlab_get_file | Get contents of a file from repository |
gitlab_get_commit | Get a single commit with full details |
gitlab_list_commits | List commits with filtering |
gitlab_get_commit_diff | Get diff for a specific commit |
gitlab_create_commit | Create a commit with multiple file actions |
gitlab_list_repository_tree | List files and directories |
gitlab_list_branches | List branches in a repository |
Search Tools (4 tools)
gitlab_search | Search across GitLab (projects, issues, MRs, code, etc.) |
gitlab_issue_search | Specialized issue search |
gitlab_blob_search | Search file content in repositories |
gitlab_merge_request_search | Specialized merge request search |
Epic Tools (9 tools)
gitlab_get_epic | Get details of a specific epic |
gitlab_list_epics | List epics for a group |
gitlab_create_epic | Create a new epic |
gitlab_update_epic | Update an existing epic |
gitlab_list_epic_issues | Get all issues associated with an epic |
gitlab_add_issue_to_epic | Link an issue to an epic |
gitlab_remove_issue_from_epic | Unlink an issue from an epic |
gitlab_list_epic_notes | List all comments on an epic |
gitlab_create_epic_note | Add a comment to an epic |
TODO Tools (4 tools)
gitlab_list_todos | List TODO items for current user |
gitlab_mark_todo_done | Mark a specific TODO as done |
gitlab_mark_all_todos_done | Mark all TODOs as done |
gitlab_get_todo_count | Get count of pending TODOs |
Project & User Tools (3 tools)
gitlab_get_project | Get details of a specific project |
gitlab_list_project_members | List members of a project |
gitlab_get_current_user | Get current user information |
Security Tools (8 tools)
gitlab_list_vulnerabilities | List security vulnerabilities |
gitlab_get_vulnerability_details | Get details for a specific vulnerability |
gitlab_create_vulnerability_issue | Create issue linked to vulnerabilities (GraphQL) |
gitlab_dismiss_vulnerability | Dismiss vulnerability with reason (GraphQL) |
gitlab_confirm_vulnerability | Confirm a security vulnerability (GraphQL) |
gitlab_revert_vulnerability_to_detected | Revert vulnerability to detected state (GraphQL) |
gitlab_update_vulnerability_severity | Update vulnerability severity level (GraphQL) |
gitlab_link_vulnerability_to_issue | Link existing issue to vulnerabilities (GraphQL) |
Note: All GraphQL-based security tools include automatic GID (Global ID) format validation to ensure correct parameter formats before making API calls.
Wiki Tools (1 tool)
gitlab_get_wiki_page | Get a wiki page with its content |
π‘ Usage Examples
Example 1: Create and Manage Issues
import gitlabPlugin from '@gitlab/opencode-gitlab-plugin';
const plugin = await gitlabPlugin({});
const issue = await plugin.tool.gitlab_create_issue.execute({
project_id: 'my-group/my-project',
title: 'Fix authentication bug',
description:
'## Problem\n\nUsers cannot login with OAuth.\n\n## Steps to Reproduce\n1. Go to login page\n2. Click OAuth button\n3. Error occurs',
labels: 'bug,authentication,priority::high',
assignee_ids: [42],
milestone_id: 10,
due_date: '2025-12-31',
});
console.log(`Issue created: ${issue.web_url}`);
await plugin.tool.gitlab_create_issue_note.execute({
project_id: 'my-group/my-project',
issue_iid: issue.iid,
body: 'I will start working on this today.',
});
const issues = await plugin.tool.gitlab_list_issues.execute({
project_id: 'my-group/my-project',
labels: 'bug',
state: 'opened',
});
Example 2: Review Merge Request
const mr = await plugin.tool.gitlab_get_merge_request.execute({
project_id: 'gitlab-org/gitlab',
mr_iid: 12345,
include_changes: true,
});
const discussions = await plugin.tool.gitlab_list_mr_discussions.execute({
project_id: 'gitlab-org/gitlab',
mr_iid: 12345,
});
await plugin.tool.gitlab_create_mr_note.execute({
project_id: 'gitlab-org/gitlab',
mr_iid: 12345,
body: 'LGTM! Great work on this feature.',
});
Example 3: Debug Failed Pipeline
const pipelines = await plugin.tool.gitlab_list_pipelines.execute({
project_id: 'my-group/my-project',
status: 'failed',
limit: 5,
});
const failedJobs = await plugin.tool.gitlab_get_pipeline_failing_jobs.execute({
project_id: 'my-group/my-project',
pipeline_id: pipelines[0].id,
});
for (const job of failedJobs) {
const log = await plugin.tool.gitlab_get_job_log.execute({
project_id: 'my-group/my-project',
job_id: job.id,
});
console.log(`Job ${job.name} failed with:\n${log}`);
}
await plugin.tool.gitlab_retry_job.execute({
project_id: 'my-group/my-project',
job_id: failedJobs[0].id,
});
Example 4: Create and Manage Epic
const epic = await plugin.tool.gitlab_create_epic.execute({
group_id: 'my-group',
title: 'Q1 2025 Features',
description: 'All features planned for Q1 2025',
start_date: '2025-01-01',
end_date: '2025-03-31',
labels: 'Q1,planning',
});
await plugin.tool.gitlab_add_issue_to_epic.execute({
group_id: 'my-group',
epic_iid: epic.iid,
issue_id: 123,
});
const epicIssues = await plugin.tool.gitlab_list_epic_issues.execute({
group_id: 'my-group',
epic_iid: epic.iid,
});
await plugin.tool.gitlab_create_epic_note.execute({
group_id: 'my-group',
epic_iid: epic.iid,
body: 'Epic created and issues linked successfully!',
});
Example 5: Search and Analyze Code
const codeResults = await plugin.tool.gitlab_blob_search.execute({
search: 'async function processPayment',
project_id: 'my-group/my-project',
limit: 10,
});
const issues = await plugin.tool.gitlab_issue_search.execute({
search: 'payment processing bug',
project_id: 'my-group/my-project',
state: 'opened',
});
const fileContent = await plugin.tool.gitlab_get_file.execute({
project_id: 'my-group/my-project',
file_path: 'src/payment/processor.ts',
ref: 'main',
});
Example 6: Manage TODOs
const todoCount = await plugin.tool.gitlab_get_todo_count.execute({});
const todos = await plugin.tool.gitlab_list_todos.execute({
state: 'pending',
type: 'MergeRequest',
limit: 20,
});
await plugin.tool.gitlab_mark_todo_done.execute({
todo_id: todos[0].id,
});
await plugin.tool.gitlab_mark_all_todos_done.execute({});
Example 7: Create Commit with Multiple Files
const commit = await plugin.tool.gitlab_create_commit.execute({
project_id: 'my-group/my-project',
branch: 'feature/new-api',
commit_message: 'feat: add new API endpoints',
actions: [
{
action: 'create',
file_path: 'src/api/v2/users.ts',
content: 'export const getUsers = async () => { ... }',
},
{
action: 'update',
file_path: 'src/api/index.ts',
content: 'export * from "./v2/users";',
},
{
action: 'delete',
file_path: 'src/api/deprecated.ts',
},
],
author_name: 'John Doe',
author_email: 'john@example.com',
});
Example 8: Manage Security Vulnerabilities
const vulnerabilities = await plugin.tool.gitlab_list_vulnerabilities.execute({
project_id: 'my-group/my-project',
state: 'detected',
severity: 'high',
report_type: 'sast',
});
const issue = await plugin.tool.gitlab_create_vulnerability_issue.execute({
project_path: 'my-group/my-project',
vulnerability_ids: ['gid://gitlab/Vulnerability/123', 'gid://gitlab/Vulnerability/124'],
});
await plugin.tool.gitlab_dismiss_vulnerability.execute({
vulnerability_id: 'gid://gitlab/Vulnerability/125',
reason: 'FALSE_POSITIVE',
comment: 'This is a test file and not part of production code',
});
await plugin.tool.gitlab_confirm_vulnerability.execute({
vulnerability_id: 'gid://gitlab/Vulnerability/126',
comment: 'Confirmed - needs immediate attention',
});
await plugin.tool.gitlab_update_vulnerability_severity.execute({
vulnerability_ids: ['gid://gitlab/Vulnerability/127'],
severity: 'CRITICAL',
comment: 'Upgrading to critical - affects production authentication',
});
await plugin.tool.gitlab_link_vulnerability_to_issue.execute({
issue_id: 'gid://gitlab/Issue/42',
vulnerability_ids: ['gid://gitlab/Vulnerability/128', 'gid://gitlab/Vulnerability/129'],
});
π§ Development
Project Structure
opencode-gitlab-plugin/
βββ src/
β βββ client/ # API client modules
β β βββ base.ts # Base client with HTTP & GraphQL methods
β β βββ security.ts # Security/vulnerability management
β β βββ issues.ts # Issue management
β β βββ merge-requests.ts # Merge request operations
β β βββ pipelines.ts # CI/CD pipeline operations
β β βββ repository.ts # Repository operations
β β βββ epics.ts # Epic management
β β βββ search.ts # Search operations
β β βββ todos.ts # TODO management
β β βββ wikis.ts # Wiki operations
β β βββ work-items.ts # Work item operations
β β βββ audit.ts # Audit events
β β βββ git.ts # Git operations
β β βββ index.ts # Client exports
β βββ tools/ # Tool definitions
β β βββ security.ts # Security tool definitions
β β βββ issues.ts # Issue tool definitions
β β βββ merge-requests.ts # MR tool definitions
β β βββ pipelines.ts # Pipeline tool definitions
β β βββ repository.ts # Repository tool definitions
β β βββ ... # Other tool definitions
β βββ index.ts # Main plugin entry point
β βββ utils.ts # Utility functions
β βββ validation.ts # GID validation utilities
βββ tests/ # Test suite (142 tests)
β βββ client/ # Client tests
β βββ tools/ # Tool tests
β βββ validation.test.ts # Validation tests
β βββ utils.test.ts # Utility tests
βββ dist/ # Compiled output (generated)
β βββ index.js # ESM bundle
β βββ index.d.ts # TypeScript definitions
βββ .husky/ # Git hooks
β βββ commit-msg # Commitlint hook
β βββ pre-commit # Lint-staged hook
βββ .gitlab-ci.yml # CI/CD pipeline configuration
βββ package.json # Package metadata
βββ tsconfig.json # TypeScript configuration
βββ vitest.config.ts # Vitest test configuration
βββ .eslintrc.json # ESLint configuration
βββ .prettierrc.json # Prettier configuration
βββ .commitlintrc.json # Commitlint configuration
βββ .releaserc.json # Semantic-release configuration
βββ CHANGELOG.md # Auto-generated changelog
βββ INSTALLATION.md # Installation guide
βββ README.md # This file
Setup Development Environment
git clone https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin.git
cd opencode-gitlab-plugin
npm install
npm run build
npm run dev
npm run lint
npm run lint:fix
npm run format
npm run format:check
Git Hooks
The project uses Husky for Git hooks:
- pre-commit: Runs lint-staged to lint and format staged files
- commit-msg: Validates commit messages using commitlint
Commit Message Convention
This project follows Conventional Commits:
<type>(<scope>): <subject>
<body>
<footer>
Types:
feat: New feature
fix: Bug fix
docs: Documentation changes
style: Code style changes (formatting, etc.)
refactor: Code refactoring
perf: Performance improvements
test: Adding or updating tests
build: Build system changes
ci: CI/CD changes
chore: Other changes (dependencies, etc.)
revert: Revert a previous commit
Examples:
git commit -m "feat: add support for GitLab wiki pages"
git commit -m "fix: handle empty API responses correctly"
git commit -m "docs: update installation instructions"
git commit -m "ci: add automated release workflow"
Building
npm run build
Testing
npm test
npm run test:watch
npm run test:coverage
Test Coverage:
- 142 tests across 18 test files
- Client tests for all API methods
- Tool tests for all tool definitions
- Validation tests for GID utilities
- GraphQL method tests
- All tests passing β
π CI/CD Pipeline
Pipeline Stages
graph LR
A[Test] --> B[Build]
B --> C[Release]
A --> A1[Lint]
A --> A2[Format Check]
A --> A3[Unit Tests]
B --> B1[TypeScript Build]
B --> B2[Generate Types]
C --> C1[Semantic Release]
C --> C2[Publish to Registry]
C --> C3[Create Git Tag]
C --> C4[Update Changelog]
Pipeline Configuration
The .gitlab-ci.yml defines the following stages:
1. Test Stage
- test:lint: Runs ESLint on source code
- test:format: Checks code formatting with Prettier
- test:unit: Runs unit tests (placeholder)
2. Build Stage
- build: Compiles TypeScript and generates artifacts
- Uses tsup for bundling
- Generates ESM output
- Creates TypeScript definitions
- Artifacts expire in 1 week
3. Release Stage
- release: Automated versioning and publishing
- Only runs on main branch
- Uses semantic-release
- Publishes to GitLab Package Registry
- Creates Git tags
- Updates CHANGELOG.md
- Artifacts never expire
Semantic Release Workflow
sequenceDiagram
participant Dev as Developer
participant Git as Git Repository
participant CI as GitLab CI
participant SR as Semantic Release
participant Reg as Package Registry
Dev->>Git: Push to main branch
Git->>CI: Trigger pipeline
CI->>CI: Run tests
CI->>CI: Build package
CI->>SR: Run semantic-release
SR->>SR: Analyze commits
SR->>SR: Determine version
SR->>SR: Generate changelog
SR->>Git: Create tag & commit
SR->>Reg: Publish package
SR->>Git: Create GitLab release
Release Process
The release process is fully automated using semantic-release:
- Commit Analysis: Analyzes commit messages since last release
- Version Calculation: Determines next version based on commit types
fix: β Patch version (1.0.x)
feat: β Minor version (1.x.0)
BREAKING CHANGE: β Major version (x.0.0)
- Changelog Generation: Updates CHANGELOG.md
- Package Publishing: Publishes to GitLab Package Registry
- Git Tagging: Creates and pushes version tag
- GitLab Release: Creates release notes on GitLab
Environment Variables
The CI/CD pipeline uses the following variables:
CI_JOB_TOKEN: GitLab CI token (automatic)
CI_PROJECT_ID: Project ID (automatic)
CI_API_V4_URL: GitLab API URL (automatic)
HUSKY: Set to 0 to disable hooks in CI
π API Reference
GitLabApiClient Class
The core API client that handles all GitLab REST API interactions.
Constructor
constructor(instanceUrl: string, token: string)
HTTP Methods
async fetch<T>(method: string, path: string, body?: unknown): Promise<T>
async fetchText(method: string, path: string): Promise<string>
GraphQL Methods
async fetchGraphQL<T>(query: string, variables?: Record<string, unknown>): Promise<T>
Features:
- Full TypeScript type safety with generic return types
- Automatic error handling for both HTTP and GraphQL errors
- Support for query variables
- Used by all GraphQL-based security tools
Example:
const result = await client.fetchGraphQL<{ vulnerability: { id: string } }>(
`mutation($id: VulnerabilityID!) {
vulnerabilityConfirm(input: { id: $id }) {
vulnerability { id state }
errors
}
}`,
{ id: 'gid://gitlab/Vulnerability/123' }
);
Project ID Encoding
private encodeProjectId(projectId: string): string
Handles URL encoding for project paths (e.g., gitlab-org/gitlab β gitlab-org%2Fgitlab)
Authentication Functions
readTokenFromAuthStorage
function readTokenFromAuthStorage(): string | undefined;
Reads GitLab token from OpenCode auth storage (~/.local/share/opencode/auth.json).
Supports:
- OAuth tokens:
{ type: "oauth", access: "token" }
- API tokens:
{ type: "api", key: "token" }
getGitLabClient
function getGitLabClient(): GitLabApiClient;
Creates and returns a configured GitLab API client.
Priority:
GITLAB_TOKEN environment variable
- OpenCode auth storage
- Throws error if no token found
Validation Functions
isValidGid
function isValidGid(gid: string, expectedType?: string): boolean;
Validates GitLab Global ID (GID) format.
Parameters:
gid - The GID to validate (e.g., gid://gitlab/Vulnerability/123)
expectedType - Optional expected resource type (e.g., 'Vulnerability', 'Issue')
Returns: true if valid, false otherwise
Example:
isValidGid('gid://gitlab/Vulnerability/123');
isValidGid('gid://gitlab/Issue/456', 'Issue');
isValidGid('gid://gitlab/Vulnerability/123', 'Issue');
isValidGid('invalid-gid');
validateGid
function validateGid(gid: string, expectedType?: string): void;
Validates GID format and throws descriptive error if invalid.
Parameters:
gid - The GID to validate
expectedType - Optional expected resource type
Throws: Error with descriptive message if GID format is invalid
Example:
validateGid('gid://gitlab/Vulnerability/123');
validateGid('invalid-gid');
validateGid('gid://gitlab/Issue/123', 'Vulnerability');
Usage in Security Tools:
All GraphQL-based security tools automatically validate GID parameters:
createVulnerabilityIssue() - validates vulnerability IDs
dismissVulnerability() - validates vulnerability ID
confirmVulnerability() - validates vulnerability ID
revertVulnerability() - validates vulnerability ID
updateVulnerabilitySeverity() - validates vulnerability IDs
linkVulnerabilityToIssue() - validates both issue ID and vulnerability IDs
Tool Schema Validation
All tools use Zod for runtime validation:
import { tool } from '@opencode-ai/plugin';
const z = tool.schema;
gitlab_get_merge_request: tool({
description: 'Get details of a specific merge request',
args: {
project_id: z.string().describe('The project ID or URL-encoded path'),
mr_iid: z.number().describe('The internal ID of the merge request'),
include_changes: z.boolean().optional().describe('Include file changes'),
},
execute: async (args, ctx) => {
},
});
Error Handling
All API calls include comprehensive error handling:
if (!response.ok) {
const errorText = await response.text();
throw new Error(`GitLab API error ${response.status}: ${errorText}`);
}
Response Formatting
All tool responses are JSON-formatted:
return JSON.stringify(result, null, 2);
π Security Considerations
Token Storage
- Environment Variables: Recommended for CI/CD and production
- Auth Storage: Convenient for local development
- Never commit tokens: Use
.gitignore for sensitive files
API Permissions
The plugin requires a GitLab token with appropriate scopes:
api: Full API access (recommended)
read_api: Read-only access (limited functionality)
read_repository: Repository read access
write_repository: Repository write access (for commits)
Rate Limiting
GitLab API has rate limits:
- Authenticated requests: 2,000 requests per minute
- Unauthenticated requests: 10 requests per minute
The plugin does not implement rate limiting logic. Consider implementing retry logic in your application.
HTTPS Only
The plugin enforces HTTPS for all API calls. HTTP URLs are not supported.
π€ Contributing
Contributions are welcome! Please follow these guidelines:
Contribution Workflow
graph TD
A[Fork Repository] --> B[Create Feature Branch]
B --> C[Make Changes]
C --> D[Write Tests]
D --> E[Run Linting]
E --> F[Commit with Convention]
F --> G[Push to Fork]
G --> H[Create Merge Request]
H --> I[Code Review]
I --> J{Approved?}
J -->|Yes| K[Merge to Main]
J -->|No| C
K --> L[Automated Release]
Steps to Contribute
-
Fork the repository
git clone https://gitlab.com/YOUR_USERNAME/editor-extensions/opencode-gitlab-plugin.git
-
Create a feature branch
git checkout -b feat/my-new-feature
-
Make your changes
- Follow TypeScript best practices
- Add JSDoc comments for public APIs
- Update documentation if needed
-
Run quality checks
npm run lint
npm run format
npm run build
npm test
-
Commit with conventional commits
git commit -m "feat: add new tool for project milestones"
-
Push and create MR
git push origin feat/my-new-feature
Code Style
- TypeScript: Strict mode enabled
- ESLint: Follow configured rules
- Prettier: Auto-format on commit
- Line Length: 100 characters max
- Indentation: 2 spaces, no tabs
Adding New Tools
To
Assistant
add a new GitLab API tool:
-
Add API method to GitLabApiClient
async getProjectMilestones(projectId: string) {
const encodedProject = this.encodeProjectId(projectId);
return this.fetch<Record<string, unknown>[]>(
'GET',
`/projects/${encodedProject}/milestones`
);
}
-
Add tool definition
gitlab_list_milestones: tool({
description: 'List milestones for a project',
args: {
project_id: z.string().describe('The project ID or path'),
state: z.enum(['active', 'closed', 'all']).optional(),
},
execute: async (args, _ctx) => {
const client = getGitLabClient();
const milestones = await client.getProjectMilestones(args.project_id);
return JSON.stringify(milestones, null, 2);
},
});
-
Update documentation
- Add tool to README.md
- Update tool count
- Add usage example if applicable
π Links
π Acknowledgments
- OpenCode Team: For the plugin SDK and framework
- GitLab: For the comprehensive REST API
- Contributors: All contributors to this project
π Support
For questions, issues, or feature requests:
Made with β€οΈ for the OpenCode community