@gitgov/core-gitlab
v1.0.0
Published
GitLab REST API provider for the GitGovernance SDK
Readme
@gitgov/core-gitlab
GitLab REST API provider for the GitGovernance SDK. Implements the same 5 core interfaces as @gitgov/core/github, but using GitLab REST API via @gitbeaker/rest.
Install
npm install @gitgov/core-gitlab
# or
pnpm add @gitgov/core-gitlabQuick Start
GitLab API Backend
For SaaS, Forge apps, or GitLab CI — no filesystem needed:
import { Gitlab } from '@gitbeaker/rest';
import {
GitLabRecordStore,
GitLabConfigStore,
GitLabGitModule,
GitLabFileLister,
} from '@gitgov/core-gitlab';
import type { TaskRecord } from '@gitgov/core';
const api = new Gitlab({ token: process.env.GITLAB_TOKEN });
const projectId = 12345; // or 'my-org/my-repo' (URL-encoded path)
const taskStore = new GitLabRecordStore<TaskRecord>({
projectId, api, basePath: '.gitgov/tasks',
});
// Read — returns parsed JSON, caches blob_id for optimistic concurrency
const task = await taskStore.get('task-001');
// Write — returns { commitSha } from the created commit
const result = await taskStore.put('task-002', newTask);
// Atomic batch — single commit for N records (NO GitModule dependency needed!)
await taskStore.putMany([
{ id: 'task-003', value: task3 },
{ id: 'task-004', value: task4 },
]);
// → 1 API call via POST /repository/commits with actions[]Full GitGovernance Setup with GitLab
Drop-in replacement for the GitHub backend — same adapters, same interfaces:
import { Gitlab } from '@gitbeaker/rest';
import { Adapters, EventBus } from '@gitgov/core';
import {
GitLabRecordStore,
GitLabConfigStore,
GitLabFileLister,
GitLabGitModule,
} from '@gitgov/core-gitlab';
import type { TaskRecord, CycleRecord, ActorRecord, AgentRecord } from '@gitgov/core';
const api = new Gitlab({ token: process.env.GITLAB_TOKEN });
const projectId = 12345;
const opts = { projectId, api, ref: 'gitgov-state' };
// Infrastructure — same interfaces as GitHub, different backend
const eventBus = new EventBus.EventBus();
const taskStore = new GitLabRecordStore<TaskRecord>({ ...opts, basePath: '.gitgov/tasks' });
const cycleStore = new GitLabRecordStore<CycleRecord>({ ...opts, basePath: '.gitgov/cycles' });
const actorStore = new GitLabRecordStore<ActorRecord>({ ...opts, basePath: '.gitgov/actors' });
const agentStore = new GitLabRecordStore<AgentRecord>({ ...opts, basePath: '.gitgov/agents' });
// Adapters compose modules — identical to GitHub setup
const identity = new Adapters.IdentityAdapter({ actorStore, agentStore });
const workflow = Adapters.WorkflowAdapter.createDefault();
const backlog = new Adapters.BacklogAdapter({
taskStore, cycleStore, identity, eventBus, workflowAdapter: workflow,
});
// Create a task — works exactly like GitHub
const task = await backlog.createTask(
{ title: 'Implement auth', priority: 'high' },
'human:project-lead',
);Comparison: GitHub vs GitLab Setup
// GitHub
import { Octokit } from '@octokit/rest';
import { GitHubRecordStore } from '@gitgov/core/github';
const octokit = new Octokit({ auth: token });
const store = new GitHubRecordStore({ owner, repo, basePath }, octokit);
// GitLab — same interface, different constructor
import { Gitlab } from '@gitbeaker/rest';
import { GitLabRecordStore } from '@gitgov/core-gitlab';
const api = new Gitlab({ token });
const store = new GitLabRecordStore({ projectId, api, basePath });
// From here on, the code is IDENTICAL:
await store.put('task-001', record);
const task = await store.get('task-001');
const ids = await store.list();Modules
| Module | Interface | Description |
|--------|-----------|-------------|
| GitLabFileLister | FileLister | Repository Tree + Files API |
| GitLabConfigStore | ConfigStore | Files API for config.json |
| GitLabRecordStore | RecordStore | Files API CRUD + Commits API batch |
| GitLabGitModule | IGitModule | Commits, Branches, Compare API |
| GitLabSyncStateModule | ISyncStateModule | Push/pull state branch |
| GitLabWebhookHandler | — | Push event processing |
Key Advantage: 1-Call Atomic Commits
GitLab's Commits API allows multi-file atomic commits in 1 API call:
const git = new GitLabGitModule({ projectId: 12345, api });
await git.add(['file1.json', 'file2.json'], {
contentMap: { 'file1.json': '...', 'file2.json': '...' }
});
await git.commit('batch update');
// → 1 POST /repository/commits with actions[]Compare with GitHub which requires 6 API calls (blob → tree → commit → ref).
Development
# Type check
pnpm typecheck
# Tests (unit — mocked Gitbeaker)
pnpm test
# Tests with coverage
pnpm test:coverageArchitecture
src/
├── index.ts # Barrel export
├── gitlab.ts # GitLabApiError, mapGitbeakerError, isGitbeakerRequestError
├── file_lister/ # GitLabFileLister
├── config_store/ # GitLabConfigStore
├── record_store/ # GitLabRecordStore
├── git/ # GitLabGitModule
├── sync_state/ # GitLabSyncStateModule
└── webhook/ # GitLabWebhookHandlerRelated
- Core SDK: github.com/gitgovernance/monorepo/packages/core
- GitHub Provider:
@gitgov/core/github(in monorepo) - Gitbeaker: github.com/jdalrymple/gitbeaker
