17 Commits

Author SHA1 Message Date
4d90bb01cf v2.5.0 2026-03-02 11:46:38 +00:00
e9dc0a7fa3 feat(gitlab): add pipelines and jobs API support, including list/get/trigger/delete/retry/cancel operations, job controls, and related types and list options 2026-03-02 11:46:38 +00:00
9feb49a3d4 v2.4.0 2026-03-02 09:32:47 +00:00
879f16dd98 feat(gitlab): add repository branches and tags endpoints and corresponding types 2026-03-02 09:32:47 +00:00
e94004742f v2.3.0 2026-02-28 16:59:43 +00:00
82940c7c0f feat(gitlab): add support for GitLab protected branches (list and unprotect) 2026-02-28 16:59:43 +00:00
016eaf1b91 v2.2.0 2026-02-28 11:13:53 +00:00
cbb9f364ae feat(gitlabclient): add deleteProject method to delete a project using GitLab API DELETE /api/v4/projects/:id 2026-02-28 11:13:53 +00:00
ef688115d6 v2.1.0 2026-02-28 10:23:20 +00:00
3aaa0f7e68 feat(gitlab): add group- and project-management methods to GitLab client 2026-02-28 10:23:20 +00:00
1cd7c62431 v2.0.3 2026-02-24 12:59:35 +00:00
8f85104136 fix(): no changes detected; nothing to commit 2026-02-24 12:59:35 +00:00
c8059fb1c0 fix(test): await async getEnvVarOnDemand calls in test setup 2026-02-24 12:59:11 +00:00
413c4be172 docs(core): add comprehensive readme with full API documentation 2026-02-24 12:57:27 +00:00
e7cfd5dec1 v2.0.2 2026-02-24 12:55:39 +00:00
e002e90bd0 fix(): no changes detected in diff; no version bump required 2026-02-24 12:55:39 +00:00
f460b92c3a fix(core): add verdaccio as primary release registry 2026-02-24 12:55:20 +00:00
9 changed files with 789 additions and 29 deletions

View File

@@ -1,5 +1,58 @@
# Changelog
## 2026-03-02 - 2.5.0 - feat(gitlab)
add pipelines and jobs API support, including list/get/trigger/delete/retry/cancel operations, job controls, and related types and list options
- Add new pipeline methods: getPipelines (with filtering, ordering and pagination), getPipeline, triggerPipeline, deletePipeline, retryPipeline, cancelPipeline, getPipelineVariables, getPipelineTestReport
- Add new job methods: getPipelineJobs (with scope filtering and pagination), getJob, retryJob, cancelJob, playJob, eraseJob; preserve getJobLog
- Introduce IPipelineListOptions and IJobListOptions for richer listing filters
- Extend and add interfaces: IGitLabPipeline (additional metadata fields), IGitLabJob (expanded fields including pipeline, runner, artifacts), IGitLabPipelineVariable, IGitLabTestReport, IGitLabTestSuite, IGitLabTestCase and other minor interface reorganizations
- Export the new interfaces from the package entry (ts/index.ts)
## 2026-03-02 - 2.4.0 - feat(gitlab)
add repository branches and tags endpoints and corresponding types
- Add getRepoBranches(projectId, opts?) to list repository branches (supports pagination with page and perPage; defaults to page=1, perPage=50).
- Add getRepoTags(projectId, opts?) to list repository tags (supports pagination with page and perPage; defaults to page=1, perPage=50).
- Introduce IGitLabBranch and IGitLabTag interfaces and export them from ts/index.ts.
## 2026-02-28 - 2.3.0 - feat(gitlab)
add support for GitLab protected branches (list and unprotect)
- Added IGitLabProtectedBranch interface
- Added GitLabClient.getProtectedBranches(projectId) returning IGitLabProtectedBranch[]
- Added GitLabClient.unprotectBranch(projectId, branchName) to remove branch protection
- Exported IGitLabProtectedBranch from index.ts
- Non-breaking API additions; recommended minor version bump
## 2026-02-28 - 2.2.0 - feat(gitlabclient)
add deleteProject method to delete a project using GitLab API DELETE /api/v4/projects/:id
- Adds GitlabClient.deleteProject(projectId: number | string): Promise<void>.
- Implements DELETE /api/v4/projects/:id and URL-encodes the projectId.
- Non-breaking API addition — bump minor version.
## 2026-02-28 - 2.1.0 - feat(gitlab)
add group- and project-management methods to GitLab client
- Adds getGroupByPath(fullPath) to fetch a group by full path
- Adds getGroupProjects(groupId, opts?) to list projects in a group (include_subgroups=true, default perPage=50, optional search)
- Adds getDescendantGroups(groupId, opts?) to list descendant subgroups (paginated, default perPage=50, optional search)
- Adds createGroup(name, path, parentId?) to create groups (defaults to private visibility)
- Adds createProject(name, opts?) to create projects with optional path, namespaceId, visibility (default private) and description
## 2026-02-24 - 2.0.3 - fix()
no changes detected; nothing to commit
- No files changed in the provided diff
- No updates to source, dependencies, or package files
## 2026-02-24 - 2.0.2 - fix()
no changes detected in diff; no version bump required
- No files changed in this commit/diff.
- No code or dependency changes detected; no release necessary.
## 2026-02-24 - 2.0.1 - fix()
no changes detected; no version bump required

View File

@@ -26,6 +26,7 @@
"@git.zone/cli": {
"release": {
"registries": [
"https://verdaccio.lossless.digital",
"https://registry.npmjs.org"
],
"accessLevel": "public"

View File

@@ -1,6 +1,6 @@
{
"name": "@apiclient.xyz/gitlab",
"version": "2.0.1",
"version": "2.5.0",
"private": false,
"description": "A TypeScript client for the GitLab API, providing easy access to projects, groups, CI/CD variables, and pipelines.",
"main": "dist_ts/index.js",

278
readme.md
View File

@@ -4,25 +4,291 @@ A TypeScript client for the GitLab API, providing easy access to projects, group
## Install
```sh
```bash
npm install @apiclient.xyz/gitlab
```
## Usage
All examples below use ESM imports and async/await.
### Creating a Client
```typescript
import { GitLabClient } from '@apiclient.xyz/gitlab';
const client = new GitLabClient('https://gitlab.com', 'your-private-token');
const client = new GitLabClient('https://gitlab.example.com', 'your-private-token');
```
// Test connection
The constructor accepts the base URL of your GitLab instance and a personal access token (or project/group token) used for authentication via the `PRIVATE-TOKEN` header.
### Testing the Connection
```typescript
const result = await client.testConnection();
// List projects
if (result.ok) {
console.log('Connected successfully.');
} else {
console.error('Connection failed:', result.error);
}
```
### Listing Projects
Retrieve projects you are a member of, ordered by most recently updated.
```typescript
// First page, default 50 per page
const projects = await client.getProjects();
// Manage CI/CD variables
await client.createProjectVariable(123, 'SECRET_KEY', 'secret-value');
// Search with pagination
const filtered = await client.getProjects({
search: 'my-service',
page: 1,
perPage: 20,
});
for (const project of filtered) {
console.log(`${project.id} - ${project.path_with_namespace}`);
}
```
### Listing Groups
```typescript
const groups = await client.getGroups();
// Search groups by name
const matchingGroups = await client.getGroups({ search: 'platform' });
for (const group of matchingGroups) {
console.log(`${group.id} - ${group.full_path}`);
}
```
### Managing Project Variables
```typescript
const projectId = 42;
// List all variables
const vars = await client.getProjectVariables(projectId);
// Create a variable
await client.createProjectVariable(projectId, 'DATABASE_URL', 'postgres://...', {
protected: true,
masked: true,
environment_scope: 'production',
});
// Update a variable
await client.updateProjectVariable(projectId, 'DATABASE_URL', 'postgres://new-host/...', {
protected: true,
});
// Delete a variable
await client.deleteProjectVariable(projectId, 'DATABASE_URL');
```
### Managing Group Variables
The group variable API mirrors the project variable API.
```typescript
const groupId = 7;
// List all variables
const groupVars = await client.getGroupVariables(groupId);
// Create a variable
await client.createGroupVariable(groupId, 'NPM_TOKEN', 'tok-xxx', {
protected: false,
masked: true,
environment_scope: '*',
});
// Update a variable
await client.updateGroupVariable(groupId, 'NPM_TOKEN', 'tok-yyy', {
masked: true,
});
// Delete a variable
await client.deleteGroupVariable(groupId, 'NPM_TOKEN');
```
### Working with Pipelines
```typescript
const projectId = 42;
// List recent pipelines
const pipelines = await client.getPipelines(projectId, { page: 1, perPage: 10 });
for (const pipeline of pipelines) {
console.log(`Pipeline #${pipeline.id} [${pipeline.status}] on ${pipeline.ref}`);
}
// Get jobs for a specific pipeline
const jobs = await client.getPipelineJobs(projectId, pipelines[0].id);
for (const job of jobs) {
console.log(` Job "${job.name}" (${job.stage}): ${job.status}`);
}
// Read the raw log output of a job
const log = await client.getJobLog(projectId, jobs[0].id);
console.log(log);
// Retry a failed pipeline
await client.retryPipeline(projectId, pipelines[0].id);
// Cancel a running pipeline
await client.cancelPipeline(projectId, pipelines[0].id);
```
## API Reference
### `GitLabClient`
| Method | Signature | Returns | Description |
|---|---|---|---|
| `constructor` | `(baseUrl: string, token: string)` | `GitLabClient` | Create a new client instance. |
| `testConnection` | `()` | `Promise<ITestConnectionResult>` | Verify the token and connectivity. |
| `getProjects` | `(opts?: IListOptions)` | `Promise<IGitLabProject[]>` | List projects you are a member of. |
| `getGroups` | `(opts?: IListOptions)` | `Promise<IGitLabGroup[]>` | List accessible groups. |
| `getProjectVariables` | `(projectId: number \| string)` | `Promise<IGitLabVariable[]>` | List all CI/CD variables for a project. |
| `createProjectVariable` | `(projectId: number \| string, key: string, value: string, opts?: IVariableOptions)` | `Promise<IGitLabVariable>` | Create a CI/CD variable on a project. |
| `updateProjectVariable` | `(projectId: number \| string, key: string, value: string, opts?: IVariableOptions)` | `Promise<IGitLabVariable>` | Update an existing project variable. |
| `deleteProjectVariable` | `(projectId: number \| string, key: string)` | `Promise<void>` | Delete a project variable. |
| `getGroupVariables` | `(groupId: number \| string)` | `Promise<IGitLabVariable[]>` | List all CI/CD variables for a group. |
| `createGroupVariable` | `(groupId: number \| string, key: string, value: string, opts?: IVariableOptions)` | `Promise<IGitLabVariable>` | Create a CI/CD variable on a group. |
| `updateGroupVariable` | `(groupId: number \| string, key: string, value: string, opts?: IVariableOptions)` | `Promise<IGitLabVariable>` | Update an existing group variable. |
| `deleteGroupVariable` | `(groupId: number \| string, key: string)` | `Promise<void>` | Delete a group variable. |
| `getPipelines` | `(projectId: number \| string, opts?: IListOptions)` | `Promise<IGitLabPipeline[]>` | List pipelines for a project, newest first. |
| `getPipelineJobs` | `(projectId: number \| string, pipelineId: number)` | `Promise<IGitLabJob[]>` | Get all jobs for a pipeline. |
| `getJobLog` | `(projectId: number \| string, jobId: number)` | `Promise<string>` | Retrieve the raw trace/log of a job. |
| `retryPipeline` | `(projectId: number \| string, pipelineId: number)` | `Promise<void>` | Retry all failed jobs in a pipeline. |
| `cancelPipeline` | `(projectId: number \| string, pipelineId: number)` | `Promise<void>` | Cancel a running pipeline. |
## Types
### `IListOptions`
Pagination and search options used by `getProjects`, `getGroups`, and `getPipelines`.
```typescript
interface IListOptions {
search?: string; // Filter results by keyword
page?: number; // Page number (default: 1)
perPage?: number; // Items per page (default: 50 for projects/groups, 30 for pipelines)
}
```
### `IVariableOptions`
Options when creating or updating CI/CD variables.
```typescript
interface IVariableOptions {
protected?: boolean; // Only expose to protected branches/tags (default: false)
masked?: boolean; // Mask the value in job logs (default: false)
environment_scope?: string; // Environment scope (default: '*' for all environments)
}
```
### `ITestConnectionResult`
```typescript
interface ITestConnectionResult {
ok: boolean;
error?: string; // Present when ok is false
}
```
### `IGitLabProject`
```typescript
interface IGitLabProject {
id: number;
name: string;
path_with_namespace: string;
description: string;
default_branch: string;
web_url: string;
visibility: string;
topics: string[];
last_activity_at: string;
}
```
### `IGitLabGroup`
```typescript
interface IGitLabGroup {
id: number;
name: string;
full_path: string;
description: string;
web_url: string;
visibility: string;
}
```
### `IGitLabVariable`
```typescript
interface IGitLabVariable {
key: string;
value: string;
variable_type: string;
protected: boolean;
masked: boolean;
environment_scope: string;
}
```
### `IGitLabPipeline`
```typescript
interface IGitLabPipeline {
id: number;
project_id: number;
status: string;
ref: string;
sha: string;
web_url: string;
duration: number;
created_at: string;
source: string;
}
```
### `IGitLabJob`
```typescript
interface IGitLabJob {
id: number;
name: string;
stage: string;
status: string;
duration: number;
}
```
### `IGitLabUser`
Returned internally by `testConnection` to verify credentials.
```typescript
interface IGitLabUser {
id: number;
username: string;
name: string;
email: string;
avatar_url: string;
web_url: string;
state: string;
}
```
## License

View File

@@ -7,8 +7,8 @@ const testQenv = new qenv.Qenv('./', '.nogit/');
let gitlabClient: GitLabClient;
tap.test('should create a GitLabClient instance', async () => {
const baseUrl = testQenv.getEnvVarOnDemand('GITLAB_BASE_URL') || 'https://gitlab.com';
const token = testQenv.getEnvVarOnDemand('GITLAB_TOKEN') || '';
const baseUrl = (await testQenv.getEnvVarOnDemand('GITLAB_BASE_URL')) || 'https://gitlab.com';
const token = (await testQenv.getEnvVarOnDemand('GITLAB_TOKEN')) || '';
gitlabClient = new GitLabClient(baseUrl, token);
expect(gitlabClient).toBeInstanceOf(GitLabClient);
});

View File

@@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@apiclient.xyz/gitlab',
version: '2.0.1',
version: '2.5.0',
description: 'A TypeScript client for the GitLab API, providing easy access to projects, groups, CI/CD variables, and pipelines.'
}

View File

@@ -6,10 +6,17 @@ import type {
IGitLabGroup,
IGitLabVariable,
IVariableOptions,
IGitLabProtectedBranch,
IGitLabBranch,
IGitLabTag,
IGitLabPipeline,
IGitLabPipelineVariable,
IGitLabTestReport,
IGitLabJob,
ITestConnectionResult,
IListOptions,
IPipelineListOptions,
IJobListOptions,
} from './gitlab.interfaces.js';
export class GitLabClient {
@@ -125,6 +132,73 @@ export class GitLabClient {
}
}
// ---------------------------------------------------------------------------
// Groups — scoped queries
// ---------------------------------------------------------------------------
/**
* Get a single group by its full path (e.g. "foss.global" or "foss.global/push.rocks")
*/
public async getGroupByPath(fullPath: string): Promise<IGitLabGroup> {
return this.request<IGitLabGroup>(
'GET',
`/api/v4/groups/${encodeURIComponent(fullPath)}`,
);
}
/**
* List projects within a group (includes subgroups when include_subgroups=true)
*/
public async getGroupProjects(groupId: number | string, opts?: IListOptions): Promise<IGitLabProject[]> {
const page = opts?.page || 1;
const perPage = opts?.perPage || 50;
let url = `/api/v4/groups/${encodeURIComponent(groupId)}/projects?include_subgroups=true&order_by=updated_at&sort=desc&page=${page}&per_page=${perPage}`;
if (opts?.search) {
url += `&search=${encodeURIComponent(opts.search)}`;
}
return this.request<IGitLabProject[]>('GET', url);
}
/**
* List all descendant groups (recursive subgroups) within a group
*/
public async getDescendantGroups(groupId: number | string, opts?: IListOptions): Promise<IGitLabGroup[]> {
const page = opts?.page || 1;
const perPage = opts?.perPage || 50;
let url = `/api/v4/groups/${encodeURIComponent(groupId)}/descendant_groups?order_by=name&sort=asc&page=${page}&per_page=${perPage}`;
if (opts?.search) {
url += `&search=${encodeURIComponent(opts.search)}`;
}
return this.request<IGitLabGroup[]>('GET', url);
}
/**
* Create a new group. Optionally nested under a parent group.
*/
public async createGroup(name: string, path: string, parentId?: number): Promise<IGitLabGroup> {
const body: any = { name, path, visibility: 'private' };
if (parentId) body.parent_id = parentId;
return this.request<IGitLabGroup>('POST', '/api/v4/groups', body);
}
/**
* Create a new project (repository).
*/
public async createProject(name: string, opts?: {
path?: string;
namespaceId?: number;
visibility?: string;
description?: string;
}): Promise<IGitLabProject> {
return this.request<IGitLabProject>('POST', '/api/v4/projects', {
name,
path: opts?.path || name,
namespace_id: opts?.namespaceId,
visibility: opts?.visibility || 'private',
description: opts?.description || '',
});
}
// ---------------------------------------------------------------------------
// Projects
// ---------------------------------------------------------------------------
@@ -265,22 +339,131 @@ export class GitLabClient {
// Pipelines
// ---------------------------------------------------------------------------
public async getPipelines(projectId: number | string, opts?: IListOptions): Promise<IGitLabPipeline[]> {
/**
* List pipelines for a project with optional filters.
* Supports status, ref, source, scope, username, date range, ordering.
*/
public async getPipelines(projectId: number | string, opts?: IPipelineListOptions): Promise<IGitLabPipeline[]> {
const page = opts?.page || 1;
const perPage = opts?.perPage || 30;
return this.request<IGitLabPipeline[]>(
const orderBy = opts?.orderBy || 'updated_at';
const sort = opts?.sort || 'desc';
let url = `/api/v4/projects/${encodeURIComponent(projectId)}/pipelines?page=${page}&per_page=${perPage}&order_by=${orderBy}&sort=${sort}`;
if (opts?.status) url += `&status=${encodeURIComponent(opts.status)}`;
if (opts?.ref) url += `&ref=${encodeURIComponent(opts.ref)}`;
if (opts?.source) url += `&source=${encodeURIComponent(opts.source)}`;
if (opts?.scope) url += `&scope=${encodeURIComponent(opts.scope)}`;
if (opts?.username) url += `&username=${encodeURIComponent(opts.username)}`;
if (opts?.updatedAfter) url += `&updated_after=${encodeURIComponent(opts.updatedAfter)}`;
if (opts?.updatedBefore) url += `&updated_before=${encodeURIComponent(opts.updatedBefore)}`;
return this.request<IGitLabPipeline[]>('GET', url);
}
/**
* Get a single pipeline's full details.
*/
public async getPipeline(projectId: number | string, pipelineId: number): Promise<IGitLabPipeline> {
return this.request<IGitLabPipeline>(
'GET',
`/api/v4/projects/${encodeURIComponent(projectId)}/pipelines?page=${page}&per_page=${perPage}&order_by=updated_at&sort=desc`,
`/api/v4/projects/${encodeURIComponent(projectId)}/pipelines/${pipelineId}`,
);
}
public async getPipelineJobs(projectId: number | string, pipelineId: number): Promise<IGitLabJob[]> {
return this.request<IGitLabJob[]>(
'GET',
`/api/v4/projects/${encodeURIComponent(projectId)}/pipelines/${pipelineId}/jobs`,
/**
* Trigger a new pipeline on the given ref, optionally with variables.
*/
public async triggerPipeline(
projectId: number | string,
ref: string,
variables?: { key: string; value: string; variable_type?: string }[],
): Promise<IGitLabPipeline> {
const body: any = { ref };
if (variables && variables.length > 0) {
body.variables = variables;
}
return this.request<IGitLabPipeline>(
'POST',
`/api/v4/projects/${encodeURIComponent(projectId)}/pipeline`,
body,
);
}
/**
* Delete a pipeline and all its jobs.
*/
public async deletePipeline(projectId: number | string, pipelineId: number): Promise<void> {
await this.request(
'DELETE',
`/api/v4/projects/${encodeURIComponent(projectId)}/pipelines/${pipelineId}`,
);
}
/**
* Get variables used in a specific pipeline run.
*/
public async getPipelineVariables(projectId: number | string, pipelineId: number): Promise<IGitLabPipelineVariable[]> {
return this.request<IGitLabPipelineVariable[]>(
'GET',
`/api/v4/projects/${encodeURIComponent(projectId)}/pipelines/${pipelineId}/variables`,
);
}
/**
* Get the test report for a pipeline.
*/
public async getPipelineTestReport(projectId: number | string, pipelineId: number): Promise<IGitLabTestReport> {
return this.request<IGitLabTestReport>(
'GET',
`/api/v4/projects/${encodeURIComponent(projectId)}/pipelines/${pipelineId}/test_report`,
);
}
public async retryPipeline(projectId: number | string, pipelineId: number): Promise<IGitLabPipeline> {
return this.request<IGitLabPipeline>(
'POST',
`/api/v4/projects/${encodeURIComponent(projectId)}/pipelines/${pipelineId}/retry`,
);
}
public async cancelPipeline(projectId: number | string, pipelineId: number): Promise<IGitLabPipeline> {
return this.request<IGitLabPipeline>(
'POST',
`/api/v4/projects/${encodeURIComponent(projectId)}/pipelines/${pipelineId}/cancel`,
);
}
// ---------------------------------------------------------------------------
// Jobs
// ---------------------------------------------------------------------------
/**
* List jobs for a pipeline with optional scope filter and pagination.
*/
public async getPipelineJobs(projectId: number | string, pipelineId: number, opts?: IJobListOptions): Promise<IGitLabJob[]> {
const page = opts?.page || 1;
const perPage = opts?.perPage || 100;
let url = `/api/v4/projects/${encodeURIComponent(projectId)}/pipelines/${pipelineId}/jobs?page=${page}&per_page=${perPage}`;
if (opts?.scope && opts.scope.length > 0) {
for (const s of opts.scope) {
url += `&scope[]=${encodeURIComponent(s)}`;
}
}
return this.request<IGitLabJob[]>('GET', url);
}
/**
* Get a single job's full details.
*/
public async getJob(projectId: number | string, jobId: number): Promise<IGitLabJob> {
return this.request<IGitLabJob>(
'GET',
`/api/v4/projects/${encodeURIComponent(projectId)}/jobs/${jobId}`,
);
}
/**
* Get a job's raw log (trace) output.
*/
public async getJobLog(projectId: number | string, jobId: number): Promise<string> {
return this.requestText(
'GET',
@@ -288,17 +471,94 @@ export class GitLabClient {
);
}
public async retryPipeline(projectId: number | string, pipelineId: number): Promise<void> {
await this.request(
/**
* Retry a single job.
*/
public async retryJob(projectId: number | string, jobId: number): Promise<IGitLabJob> {
return this.request<IGitLabJob>(
'POST',
`/api/v4/projects/${encodeURIComponent(projectId)}/pipelines/${pipelineId}/retry`,
`/api/v4/projects/${encodeURIComponent(projectId)}/jobs/${jobId}/retry`,
);
}
public async cancelPipeline(projectId: number | string, pipelineId: number): Promise<void> {
/**
* Cancel a running job.
*/
public async cancelJob(projectId: number | string, jobId: number): Promise<IGitLabJob> {
return this.request<IGitLabJob>(
'POST',
`/api/v4/projects/${encodeURIComponent(projectId)}/jobs/${jobId}/cancel`,
);
}
/**
* Trigger a manual job (play action).
*/
public async playJob(projectId: number | string, jobId: number): Promise<IGitLabJob> {
return this.request<IGitLabJob>(
'POST',
`/api/v4/projects/${encodeURIComponent(projectId)}/jobs/${jobId}/play`,
);
}
/**
* Erase a job's trace and artifacts.
*/
public async eraseJob(projectId: number | string, jobId: number): Promise<void> {
await this.request(
'POST',
`/api/v4/projects/${encodeURIComponent(projectId)}/pipelines/${pipelineId}/cancel`,
`/api/v4/projects/${encodeURIComponent(projectId)}/jobs/${jobId}/erase`,
);
}
// ---------------------------------------------------------------------------
// Repository Branches & Tags
// ---------------------------------------------------------------------------
public async getRepoBranches(projectId: number | string, opts?: IListOptions): Promise<IGitLabBranch[]> {
const page = opts?.page || 1;
const perPage = opts?.perPage || 50;
return this.request<IGitLabBranch[]>(
'GET',
`/api/v4/projects/${encodeURIComponent(projectId)}/repository/branches?page=${page}&per_page=${perPage}`,
);
}
public async getRepoTags(projectId: number | string, opts?: IListOptions): Promise<IGitLabTag[]> {
const page = opts?.page || 1;
const perPage = opts?.perPage || 50;
return this.request<IGitLabTag[]>(
'GET',
`/api/v4/projects/${encodeURIComponent(projectId)}/repository/tags?page=${page}&per_page=${perPage}`,
);
}
// ---------------------------------------------------------------------------
// Protected Branches
// ---------------------------------------------------------------------------
public async getProtectedBranches(projectId: number | string): Promise<IGitLabProtectedBranch[]> {
return this.request<IGitLabProtectedBranch[]>(
'GET',
`/api/v4/projects/${encodeURIComponent(projectId)}/protected_branches`,
);
}
public async unprotectBranch(projectId: number | string, branchName: string): Promise<void> {
await this.request(
'DELETE',
`/api/v4/projects/${encodeURIComponent(projectId)}/protected_branches/${encodeURIComponent(branchName)}`,
);
}
// ---------------------------------------------------------------------------
// Project Deletion
// ---------------------------------------------------------------------------
public async deleteProject(projectId: number | string): Promise<void> {
await this.request(
'DELETE',
`/api/v4/projects/${encodeURIComponent(projectId)}`,
);
}
}

View File

@@ -1,3 +1,52 @@
// ---------------------------------------------------------------------------
// Common
// ---------------------------------------------------------------------------
export interface ITestConnectionResult {
ok: boolean;
error?: string;
}
export interface IListOptions {
search?: string;
page?: number;
perPage?: number;
}
// ---------------------------------------------------------------------------
// Pipeline / Job list options
// ---------------------------------------------------------------------------
export interface IPipelineListOptions extends IListOptions {
/** Filter by pipeline status */
status?: string;
/** Filter by branch or tag ref */
ref?: string;
/** Filter by trigger source (push, web, trigger, schedule, api, external, pipeline, chat, merge_request_event, …) */
source?: string;
/** Filter by scope (running, pending, finished, branches, tags) */
scope?: string;
/** Filter by the user who triggered the pipeline */
username?: string;
/** Return pipelines updated after this ISO 8601 date */
updatedAfter?: string;
/** Return pipelines updated before this ISO 8601 date */
updatedBefore?: string;
/** Order by field (id, status, ref, updated_at, user_id). Default: id */
orderBy?: string;
/** Sort direction (asc, desc). Default: desc */
sort?: string;
}
export interface IJobListOptions extends IListOptions {
/** Filter by job scope(s) */
scope?: string[];
}
// ---------------------------------------------------------------------------
// Users
// ---------------------------------------------------------------------------
export interface IGitLabUser {
id: number;
username: string;
@@ -8,6 +57,10 @@ export interface IGitLabUser {
state: string;
}
// ---------------------------------------------------------------------------
// Projects
// ---------------------------------------------------------------------------
export interface IGitLabProject {
id: number;
name: string;
@@ -20,6 +73,10 @@ export interface IGitLabProject {
last_activity_at: string;
}
// ---------------------------------------------------------------------------
// Groups
// ---------------------------------------------------------------------------
export interface IGitLabGroup {
id: number;
name: string;
@@ -29,6 +86,10 @@ export interface IGitLabGroup {
visibility: string;
}
// ---------------------------------------------------------------------------
// Variables
// ---------------------------------------------------------------------------
export interface IGitLabVariable {
key: string;
value: string;
@@ -44,33 +105,143 @@ export interface IVariableOptions {
environment_scope?: string;
}
// ---------------------------------------------------------------------------
// Protected Branches
// ---------------------------------------------------------------------------
export interface IGitLabProtectedBranch {
id: number;
name: string;
allow_force_push: boolean;
}
// ---------------------------------------------------------------------------
// Pipelines
// ---------------------------------------------------------------------------
export interface IGitLabPipeline {
id: number;
iid: number;
project_id: number;
status: string;
ref: string;
sha: string;
before_sha: string;
tag: boolean;
web_url: string;
duration: number;
queued_duration: number;
created_at: string;
updated_at: string;
started_at: string;
finished_at: string;
source: string;
coverage: string;
user: IGitLabUser;
detailed_status: {
icon: string;
text: string;
label: string;
group: string;
tooltip: string;
has_details: boolean;
details_path: string;
favicon: string;
};
yaml_errors: string;
}
export interface IGitLabPipelineVariable {
key: string;
value: string;
variable_type: string;
}
export interface IGitLabTestReport {
total_time: number;
total_count: number;
success_count: number;
failed_count: number;
skipped_count: number;
error_count: number;
test_suites: IGitLabTestSuite[];
}
export interface IGitLabTestSuite {
name: string;
total_time: number;
total_count: number;
success_count: number;
failed_count: number;
skipped_count: number;
error_count: number;
test_cases: IGitLabTestCase[];
}
export interface IGitLabTestCase {
status: string;
name: string;
classname: string;
execution_time: number;
system_output: string;
stack_trace: string;
}
// ---------------------------------------------------------------------------
// Jobs
// ---------------------------------------------------------------------------
export interface IGitLabJob {
id: number;
name: string;
stage: string;
status: string;
ref: string;
tag: boolean;
web_url: string;
created_at: string;
started_at: string;
finished_at: string;
duration: number;
queued_duration: number;
coverage: number;
allow_failure: boolean;
failure_reason: string;
pipeline: {
id: number;
project_id: number;
ref: string;
sha: string;
status: string;
};
user: IGitLabUser;
runner: {
id: number;
description: string;
active: boolean;
is_shared: boolean;
};
artifacts: {
filename: string;
size: number;
}[];
artifacts_expire_at: string;
}
export interface ITestConnectionResult {
ok: boolean;
error?: string;
// ---------------------------------------------------------------------------
// Branches & Tags
// ---------------------------------------------------------------------------
export interface IGitLabBranch {
name: string;
commit: {
id: string;
};
}
export interface IListOptions {
search?: string;
page?: number;
perPage?: number;
export interface IGitLabTag {
name: string;
commit: {
id: string;
};
}

View File

@@ -4,10 +4,19 @@ export type {
IGitLabProject,
IGitLabGroup,
IGitLabVariable,
IGitLabProtectedBranch,
IGitLabBranch,
IGitLabTag,
IVariableOptions,
IGitLabPipeline,
IGitLabPipelineVariable,
IGitLabTestReport,
IGitLabTestSuite,
IGitLabTestCase,
IGitLabJob,
ITestConnectionResult,
IListOptions,
IPipelineListOptions,
IJobListOptions,
} from './gitlab.interfaces.js';
export { commitinfo } from './00_commitinfo_data.js';