1
0
Fork 0

feat(remote): implement issue, label update methods for gitlab, add dryrun support

This commit is contained in:
ssube 2020-08-23 12:13:52 -05:00
parent 9f85e22196
commit e3351fe344
Signed by: ssube
GPG Key ID: 3EED7B957D362AF1
19 changed files with 204 additions and 217 deletions

View File

@ -1,22 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [cautious-journey](./cautious-journey.md) &gt; [GithubRemote](./cautious-journey.githubremote.md) &gt; [formatBody](./cautious-journey.githubremote.formatbody.md)
## GithubRemote.formatBody() method
<b>Signature:</b>
```typescript
formatBody(options: CommentUpdate): string;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| options | CommentUpdate | |
<b>Returns:</b>
string

View File

@ -9,8 +9,10 @@ Github/Octokit API implementation of the `Remote` contract.
<b>Signature:</b> <b>Signature:</b>
```typescript ```typescript
export declare class GithubRemote implements Remote export declare class GithubRemote extends BaseRemote<Octokit, RemoteOptions> implements Remote
``` ```
<b>Extends:</b> BaseRemote&lt;Octokit, [RemoteOptions](./cautious-journey.remoteoptions.md)<!-- -->&gt;
<b>Implements:</b> [Remote](./cautious-journey.remote.md) <b>Implements:</b> [Remote](./cautious-journey.remote.md)
## Constructors ## Constructors
@ -19,15 +21,6 @@ export declare class GithubRemote implements Remote
| --- | --- | --- | | --- | --- | --- |
| [(constructor)(options)](./cautious-journey.githubremote._constructor_.md) | | Constructs a new instance of the <code>GithubRemote</code> class | | [(constructor)(options)](./cautious-journey.githubremote._constructor_.md) | | Constructs a new instance of the <code>GithubRemote</code> class |
## Properties
| Property | Modifiers | Type | Description |
| --- | --- | --- | --- |
| [options](./cautious-journey.githubremote.options.md) | | [RemoteOptions](./cautious-journey.remoteoptions.md) | |
| [request](./cautious-journey.githubremote.request.md) | | Octokit | Github API client. Will not be set for a dry run. |
| [writeCapable](./cautious-journey.githubremote.writecapable.md) | | boolean | |
| [writeRequest](./cautious-journey.githubremote.writerequest.md) | | Octokit | |
## Methods ## Methods
| Method | Modifiers | Description | | Method | Modifiers | Description |
@ -36,12 +29,11 @@ export declare class GithubRemote implements Remote
| [createComment(options)](./cautious-journey.githubremote.createcomment.md) | | | | [createComment(options)](./cautious-journey.githubremote.createcomment.md) | | |
| [createLabel(options)](./cautious-journey.githubremote.createlabel.md) | | | | [createLabel(options)](./cautious-journey.githubremote.createlabel.md) | | |
| [deleteLabel(options)](./cautious-journey.githubremote.deletelabel.md) | | | | [deleteLabel(options)](./cautious-journey.githubremote.deletelabel.md) | | |
| [formatBody(options)](./cautious-journey.githubremote.formatbody.md) | | |
| [getIssue()](./cautious-journey.githubremote.getissue.md) | | | | [getIssue()](./cautious-journey.githubremote.getissue.md) | | |
| [getLabel()](./cautious-journey.githubremote.getlabel.md) | | | | [getLabel()](./cautious-journey.githubremote.getlabel.md) | | |
| [listIssues(options)](./cautious-journey.githubremote.listissues.md) | | | | [listIssues(options)](./cautious-journey.githubremote.listissues.md) | | |
| [listLabels(options)](./cautious-journey.githubremote.listlabels.md) | | | | [listLabels(options)](./cautious-journey.githubremote.listlabels.md) | | |
| [splitProject(project)](./cautious-journey.githubremote.splitproject.md) | | | | [resolvePath(project)](./cautious-journey.githubremote.resolvepath.md) | | |
| [updateIssue(options)](./cautious-journey.githubremote.updateissue.md) | | | | [updateIssue(options)](./cautious-journey.githubremote.updateissue.md) | | |
| [updateLabel(options)](./cautious-journey.githubremote.updatelabel.md) | | | | [updateLabel(options)](./cautious-journey.githubremote.updatelabel.md) | | |

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [cautious-journey](./cautious-journey.md) &gt; [GithubRemote](./cautious-journey.githubremote.md) &gt; [options](./cautious-journey.githubremote.options.md)
## GithubRemote.options property
<b>Signature:</b>
```typescript
protected options: RemoteOptions;
```

View File

@ -1,13 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [cautious-journey](./cautious-journey.md) &gt; [GithubRemote](./cautious-journey.githubremote.md) &gt; [request](./cautious-journey.githubremote.request.md)
## GithubRemote.request property
Github API client. Will not be set for a dry run.
<b>Signature:</b>
```typescript
protected request?: Octokit;
```

View File

@ -1,13 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. --> <!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [cautious-journey](./cautious-journey.md) &gt; [GithubRemote](./cautious-journey.githubremote.md) &gt; [splitProject](./cautious-journey.githubremote.splitproject.md) [Home](./index.md) &gt; [cautious-journey](./cautious-journey.md) &gt; [GithubRemote](./cautious-journey.githubremote.md) &gt; [resolvePath](./cautious-journey.githubremote.resolvepath.md)
## GithubRemote.splitProject() method ## GithubRemote.resolvePath() method
<b>Signature:</b> <b>Signature:</b>
```typescript ```typescript
splitProject(project: string): Promise<{ resolvePath(project: string): Promise<{
owner: string; owner: string;
repo: string; repo: string;
}>; }>;

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [cautious-journey](./cautious-journey.md) &gt; [GithubRemote](./cautious-journey.githubremote.md) &gt; [writeCapable](./cautious-journey.githubremote.writecapable.md)
## GithubRemote.writeCapable property
<b>Signature:</b>
```typescript
protected get writeCapable(): boolean;
```

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [cautious-journey](./cautious-journey.md) &gt; [GithubRemote](./cautious-journey.githubremote.md) &gt; [writeRequest](./cautious-journey.githubremote.writerequest.md)
## GithubRemote.writeRequest property
<b>Signature:</b>
```typescript
protected get writeRequest(): Octokit;
```

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [cautious-journey](./cautious-journey.md) &gt; [GitlabRemote](./cautious-journey.gitlabremote.md) &gt; [client](./cautious-journey.gitlabremote.client.md)
## GitlabRemote.client property
<b>Signature:</b>
```typescript
protected client?: RemoteBundle;
```

View File

@ -7,8 +7,15 @@
<b>Signature:</b> <b>Signature:</b>
```typescript ```typescript
createComment(): Promise<void>; createComment(options: CommentUpdate): Promise<void>;
``` ```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| options | CommentUpdate | |
<b>Returns:</b> <b>Returns:</b>
Promise&lt;void&gt; Promise&lt;void&gt;

View File

@ -7,8 +7,15 @@
<b>Signature:</b> <b>Signature:</b>
```typescript ```typescript
createLabel(): Promise<LabelUpdate>; createLabel(options: LabelUpdate): Promise<LabelUpdate>;
``` ```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| options | LabelUpdate | |
<b>Returns:</b> <b>Returns:</b>
Promise&lt;LabelUpdate&gt; Promise&lt;LabelUpdate&gt;

View File

@ -7,8 +7,15 @@
<b>Signature:</b> <b>Signature:</b>
```typescript ```typescript
deleteLabel(): Promise<LabelUpdate>; deleteLabel(options: LabelUpdate): Promise<LabelUpdate>;
``` ```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| options | LabelUpdate | |
<b>Returns:</b> <b>Returns:</b>
Promise&lt;LabelUpdate&gt; Promise&lt;LabelUpdate&gt;

View File

@ -9,8 +9,10 @@ Gitlab API implementation of the `Remote` contract.
<b>Signature:</b> <b>Signature:</b>
```typescript ```typescript
export declare class GitlabRemote implements Remote export declare class GitlabRemote extends BaseRemote<RemoteBundle, RemoteOptions> implements Remote
``` ```
<b>Extends:</b> BaseRemote&lt;RemoteBundle, [RemoteOptions](./cautious-journey.remoteoptions.md)<!-- -->&gt;
<b>Implements:</b> [Remote](./cautious-journey.remote.md) <b>Implements:</b> [Remote](./cautious-journey.remote.md)
## Constructors ## Constructors
@ -19,26 +21,19 @@ export declare class GitlabRemote implements Remote
| --- | --- | --- | | --- | --- | --- |
| [(constructor)(options)](./cautious-journey.gitlabremote._constructor_.md) | | Constructs a new instance of the <code>GitlabRemote</code> class | | [(constructor)(options)](./cautious-journey.gitlabremote._constructor_.md) | | Constructs a new instance of the <code>GitlabRemote</code> class |
## Properties
| Property | Modifiers | Type | Description |
| --- | --- | --- | --- |
| [client](./cautious-journey.gitlabremote.client.md) | | RemoteBundle | |
| [options](./cautious-journey.gitlabremote.options.md) | | [RemoteOptions](./cautious-journey.remoteoptions.md) | |
## Methods ## Methods
| Method | Modifiers | Description | | Method | Modifiers | Description |
| --- | --- | --- | | --- | --- | --- |
| [connect()](./cautious-journey.gitlabremote.connect.md) | | | | [connect()](./cautious-journey.gitlabremote.connect.md) | | |
| [createComment()](./cautious-journey.gitlabremote.createcomment.md) | | | | [createComment(options)](./cautious-journey.gitlabremote.createcomment.md) | | |
| [createLabel()](./cautious-journey.gitlabremote.createlabel.md) | | | | [createLabel(options)](./cautious-journey.gitlabremote.createlabel.md) | | |
| [deleteLabel()](./cautious-journey.gitlabremote.deletelabel.md) | | | | [deleteLabel(options)](./cautious-journey.gitlabremote.deletelabel.md) | | |
| [getIssue()](./cautious-journey.gitlabremote.getissue.md) | | | | [getIssue()](./cautious-journey.gitlabremote.getissue.md) | | |
| [getLabel()](./cautious-journey.gitlabremote.getlabel.md) | | | | [getLabel()](./cautious-journey.gitlabremote.getlabel.md) | | |
| [listIssues(options)](./cautious-journey.gitlabremote.listissues.md) | | | | [listIssues(options)](./cautious-journey.gitlabremote.listissues.md) | | |
| [listLabels(options)](./cautious-journey.gitlabremote.listlabels.md) | | | | [listLabels(options)](./cautious-journey.gitlabremote.listlabels.md) | | |
| [resolvePath(path)](./cautious-journey.gitlabremote.resolvepath.md) | | | | [resolvePath(path)](./cautious-journey.gitlabremote.resolvepath.md) | | |
| [updateIssue()](./cautious-journey.gitlabremote.updateissue.md) | | | | [updateIssue(options)](./cautious-journey.gitlabremote.updateissue.md) | | |
| [updateLabel()](./cautious-journey.gitlabremote.updatelabel.md) | | | | [updateLabel(options)](./cautious-journey.gitlabremote.updatelabel.md) | | |

View File

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [cautious-journey](./cautious-journey.md) &gt; [GitlabRemote](./cautious-journey.gitlabremote.md) &gt; [options](./cautious-journey.gitlabremote.options.md)
## GitlabRemote.options property
<b>Signature:</b>
```typescript
protected options: RemoteOptions;
```

View File

@ -7,8 +7,15 @@
<b>Signature:</b> <b>Signature:</b>
```typescript ```typescript
updateIssue(): Promise<IssueUpdate>; updateIssue(options: IssueUpdate): Promise<IssueUpdate>;
``` ```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| options | IssueUpdate | |
<b>Returns:</b> <b>Returns:</b>
Promise&lt;IssueUpdate&gt; Promise&lt;IssueUpdate&gt;

View File

@ -7,8 +7,15 @@
<b>Signature:</b> <b>Signature:</b>
```typescript ```typescript
updateLabel(): Promise<LabelUpdate>; updateLabel(options: LabelUpdate): Promise<LabelUpdate>;
``` ```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| options | LabelUpdate | |
<b>Returns:</b> <b>Returns:</b>
Promise&lt;LabelUpdate&gt; Promise&lt;LabelUpdate&gt;

View File

@ -3,7 +3,7 @@ $id: cautious-journey
definitions: definitions:
hex-string: hex-string:
type: string type: string
pattern: "[0-9a-fA-F]{6}" pattern: "^[0-9a-fA-F]{6}$"
label-ref: label-ref:
type: object type: object

68
src/remote/base.ts Normal file
View File

@ -0,0 +1,68 @@
import { doesExist, InvalidArgumentError } from '@apextoaster/js-utils';
import { CommentUpdate, IssueQuery, IssueUpdate, LabelQuery, LabelUpdate, ProjectQuery, Remote, RemoteOptions } from '.';
import { ChangeVerb } from '../resolve';
import { VERSION_INFO } from '../version';
export abstract class BaseRemote<TClient, TOptions extends RemoteOptions> implements Remote {
protected client?: TClient;
protected options: TOptions;
constructor(options: TOptions) {
this.options = options;
}
public abstract connect(): Promise<boolean>;
public abstract createComment(options: CommentUpdate): Promise<unknown>;
public abstract createLabel(options: LabelUpdate): Promise<LabelUpdate>;
public abstract deleteLabel(options: LabelQuery): Promise<LabelQuery>;
public abstract getIssue(options: IssueQuery): Promise<Array<IssueUpdate>>;
public abstract getLabel(options: LabelQuery): Promise<Array<LabelUpdate>>;
public abstract listIssues(options: ProjectQuery): Promise<Array<IssueUpdate>>;
public abstract listLabels(options: ProjectQuery): Promise<Array<LabelUpdate>>;
public abstract updateIssue(options: IssueUpdate): Promise<IssueUpdate>;
public abstract updateLabel(options: LabelUpdate): Promise<LabelUpdate>;
public formatBody(options: CommentUpdate): string {
const lines = [];
lines.push(`${VERSION_INFO.package.name} v${VERSION_INFO.package.version} has updated the labels on this issue!`);
lines.push('');
for (const change of options.changes) {
switch (change.effect) {
case ChangeVerb.CONFLICTED:
lines.push(`- \`${change.label}\` conflicted with \`${change.cause}\`.`);
break;
case ChangeVerb.CREATED:
lines.push(`- \`${change.label}\` was created by \`${change.cause}\`.`);
break;
case ChangeVerb.EXISTING:
lines.push(`- \`${change.label}\` already existed.`);
break;
case ChangeVerb.REMOVED:
lines.push(`- \`${change.label}\` was removed by \`${change.cause}\`.`);
break;
case ChangeVerb.REQUIRED:
lines.push(`- \`${change.label}\` was removed because it requires \`${change.cause}\`.`);
break;
default:
lines.push(`- an unknown change occurred: \`${JSON.stringify(change)}\`.`);
break;
}
}
return lines.join('\n');
}
protected get writeCapable(): boolean {
return this.options.dryrun === false;
}
protected get writeClient(): TClient {
if (doesExist(this.client)) {
return this.client;
} else {
throw new InvalidArgumentError();
}
}
}

View File

@ -1,24 +1,17 @@
import { doesExist, InvalidArgumentError, mustExist, NotImplementedError } from '@apextoaster/js-utils'; import { InvalidArgumentError, mustExist, NotImplementedError } from '@apextoaster/js-utils';
import { createAppAuth } from '@octokit/auth-app'; import { createAppAuth } from '@octokit/auth-app';
import { Octokit } from '@octokit/rest'; import { Octokit } from '@octokit/rest';
import { CommentUpdate, IssueUpdate, LabelQuery, LabelUpdate, ProjectQuery, Remote, RemoteOptions } from '.'; import { CommentUpdate, IssueUpdate, LabelQuery, LabelUpdate, ProjectQuery, Remote, RemoteOptions } from '.';
import { ChangeVerb } from '../resolve'; import { BaseRemote } from './base';
import { VERSION_INFO } from '../version';
/** /**
* Github/Octokit API implementation of the `Remote` contract. * Github/Octokit API implementation of the `Remote` contract.
*/ */
export class GithubRemote implements Remote { export class GithubRemote extends BaseRemote<Octokit, RemoteOptions> implements Remote {
protected options: RemoteOptions;
/**
* Github API client. Will not be set for a dry run.
*/
protected request?: Octokit;
constructor(options: RemoteOptions) { constructor(options: RemoteOptions) {
this.options = options; super(options);
this.options.logger.debug(options, 'created github remote'); this.options.logger.debug(options, 'created github remote');
} }
@ -30,7 +23,7 @@ export class GithubRemote implements Remote {
switch (type) { switch (type) {
case 'app': case 'app':
this.options.logger.info('using app auth'); this.options.logger.info('using app auth');
this.request = new Octokit({ this.client = new Octokit({
auth: { auth: {
id: parseInt(mustExist(this.options.data.id), 10), id: parseInt(mustExist(this.options.data.id), 10),
installationId: parseInt(mustExist(this.options.data.installationId), 10), installationId: parseInt(mustExist(this.options.data.installationId), 10),
@ -41,7 +34,7 @@ export class GithubRemote implements Remote {
break; break;
case 'token': case 'token':
this.options.logger.info('using token auth'); this.options.logger.info('using token auth');
this.request = new Octokit({ this.client = new Octokit({
auth: mustExist(this.options.data.token), auth: mustExist(this.options.data.token),
}); });
break; break;
@ -52,7 +45,7 @@ export class GithubRemote implements Remote {
return true; return true;
} }
public async splitProject(project: string): Promise<{ public async resolvePath(project: string): Promise<{
owner: string; owner: string;
repo: string; repo: string;
}> { }> {
@ -64,7 +57,7 @@ export class GithubRemote implements Remote {
} }
public async createComment(options: CommentUpdate): Promise<unknown> { public async createComment(options: CommentUpdate): Promise<unknown> {
const path = await this.splitProject(options.project); const path = await this.resolvePath(options.project);
const body = this.formatBody(options); const body = this.formatBody(options);
this.options.logger.debug({ this.options.logger.debug({
@ -74,7 +67,7 @@ export class GithubRemote implements Remote {
}, 'creating issue comment'); }, 'creating issue comment');
if (this.writeCapable) { if (this.writeCapable) {
await this.writeRequest.issues.createComment({ await this.writeClient.issues.createComment({
body, body,
/* eslint-disable-next-line camelcase */ /* eslint-disable-next-line camelcase */
issue_number: parseInt(options.issue, 10), issue_number: parseInt(options.issue, 10),
@ -87,11 +80,11 @@ export class GithubRemote implements Remote {
} }
public async createLabel(options: LabelUpdate): Promise<LabelUpdate> { public async createLabel(options: LabelUpdate): Promise<LabelUpdate> {
const path = await this.splitProject(options.project); const path = await this.resolvePath(options.project);
// TODO: check if the label already exists // TODO: check if the label already exists
if (this.writeCapable) { if (this.writeCapable) {
await this.writeRequest.issues.createLabel({ await this.writeClient.issues.createLabel({
color: options.color, color: options.color,
description: options.desc, description: options.desc,
name: options.name, name: options.name,
@ -104,11 +97,11 @@ export class GithubRemote implements Remote {
} }
public async deleteLabel(options: LabelQuery): Promise<LabelQuery> { public async deleteLabel(options: LabelQuery): Promise<LabelQuery> {
const path = await this.splitProject(options.project); const path = await this.resolvePath(options.project);
// TODO: check if the label is in use // TODO: check if the label is in use
if (this.writeCapable) { if (this.writeCapable) {
await this.writeRequest.issues.deleteLabel({ await this.writeClient.issues.deleteLabel({
name: options.name, name: options.name,
owner: path.owner, owner: path.owner,
repo: path.repo, repo: path.repo,
@ -127,11 +120,11 @@ export class GithubRemote implements Remote {
} }
public async listIssues(options: ProjectQuery): Promise<Array<IssueUpdate>> { public async listIssues(options: ProjectQuery): Promise<Array<IssueUpdate>> {
const path = await this.splitProject(options.project); const path = await this.resolvePath(options.project);
const issues: Array<IssueUpdate> = []; const issues: Array<IssueUpdate> = [];
const repo = await mustExist(this.request).issues.listForRepo(path); const repo = await mustExist(this.client).issues.listForRepo(path);
for (const issue of repo.data) { for (const issue of repo.data) {
issues.push({ issues.push({
issue: issue.number.toString(), issue: issue.number.toString(),
@ -145,11 +138,11 @@ export class GithubRemote implements Remote {
} }
public async listLabels(options: ProjectQuery): Promise<Array<LabelUpdate>> { public async listLabels(options: ProjectQuery): Promise<Array<LabelUpdate>> {
const path = await this.splitProject(options.project); const path = await this.resolvePath(options.project);
const labels: Array<LabelUpdate> = []; const labels: Array<LabelUpdate> = [];
const repo = await mustExist(this.request).issues.listLabelsForRepo(path); const repo = await mustExist(this.client).issues.listLabelsForRepo(path);
for (const label of repo.data) { for (const label of repo.data) {
labels.push({ labels.push({
color: label.color, color: label.color,
@ -163,10 +156,10 @@ export class GithubRemote implements Remote {
} }
public async updateIssue(options: IssueUpdate): Promise<IssueUpdate> { public async updateIssue(options: IssueUpdate): Promise<IssueUpdate> {
const path = await this.splitProject(options.project); const path = await this.resolvePath(options.project);
if (this.writeCapable) { if (this.writeCapable) {
const data = await this.writeRequest.issues.setLabels({ const data = await this.writeClient.issues.setLabels({
/* eslint-disable-next-line camelcase */ /* eslint-disable-next-line camelcase */
issue_number: parseInt(options.issue, 10), issue_number: parseInt(options.issue, 10),
labels: options.labels, labels: options.labels,
@ -181,10 +174,10 @@ export class GithubRemote implements Remote {
} }
public async updateLabel(options: LabelUpdate): Promise<LabelUpdate> { public async updateLabel(options: LabelUpdate): Promise<LabelUpdate> {
const path = await this.splitProject(options.project); const path = await this.resolvePath(options.project);
if (this.writeCapable) { if (this.writeCapable) {
const data = await this.writeRequest.issues.updateLabel({ const data = await this.writeClient.issues.updateLabel({
color: options.color, color: options.color,
description: options.desc, description: options.desc,
name: options.name, name: options.name,
@ -202,47 +195,4 @@ export class GithubRemote implements Remote {
return options; return options;
} }
} }
public formatBody(options: CommentUpdate): string {
const lines = [];
lines.push(`${VERSION_INFO.package.name} v${VERSION_INFO.package.version} has updated the labels on this issue!`);
lines.push('');
for (const change of options.changes) {
switch (change.effect) {
case ChangeVerb.CONFLICTED:
lines.push(`- \`${change.label}\` conflicted with \`${change.cause}\`.`);
break;
case ChangeVerb.CREATED:
lines.push(`- \`${change.label}\` was created by \`${change.cause}\`.`);
break;
case ChangeVerb.EXISTING:
lines.push(`- \`${change.label}\` already existed.`);
break;
case ChangeVerb.REMOVED:
lines.push(`- \`${change.label}\` was removed by \`${change.cause}\`.`);
break;
case ChangeVerb.REQUIRED:
lines.push(`- \`${change.label}\` was removed because it requires \`${change.cause}\`.`);
break;
default:
lines.push(`- an unknown change occurred: \`${JSON.stringify(change)}\`.`);
break;
}
}
return lines.join('\n');
}
protected get writeCapable(): boolean {
return this.options.dryrun === false;
}
protected get writeRequest(): Octokit {
if (doesExist(this.request)) {
return this.request;
} else {
throw new InvalidArgumentError();
}
}
} }

View File

@ -1,16 +1,20 @@
import { mustExist, NotImplementedError } from '@apextoaster/js-utils'; import { mustExist, NotImplementedError } from '@apextoaster/js-utils';
import { GetResponse } from '@gitbeaker/core/dist/types/infrastructure/RequestHelper'; import { GetResponse } from '@gitbeaker/core/dist/types/infrastructure/RequestHelper';
import { Bundle } from '@gitbeaker/core/dist/types/infrastructure/Utils'; import { Bundle } from '@gitbeaker/core/dist/types/infrastructure/Utils';
import { Issues, Labels, Projects, ProjectsBundle } from '@gitbeaker/node'; import { IssueNotes, Issues, Labels, Projects, ProjectsBundle } from '@gitbeaker/node';
import { IssueQuery, IssueUpdate, LabelUpdate, ProjectQuery, Remote, RemoteOptions } from '.'; import { CommentUpdate, IssueQuery, IssueUpdate, LabelUpdate, ProjectQuery, Remote, RemoteOptions } from '.';
import { BaseRemote } from './base';
/* eslint-disable no-console */
// gitbeaker exports the bundle types as const, breaking typeof // gitbeaker exports the bundle types as const, breaking typeof
type RemoteBundle = InstanceType<Bundle<{ type RemoteBundle = InstanceType<Bundle<{
Issues: typeof Issues; Issues: typeof Issues;
IssueNotes: typeof IssueNotes;
Labels: typeof Labels; Labels: typeof Labels;
Projects: typeof Projects; Projects: typeof Projects;
}, 'Issues' | 'Labels' | 'Projects'>>; }, 'Issues' | 'IssueNotes' | 'Labels' | 'Projects'>>;
export function unwrapResponse<T>(resp: GetResponse): T { export function unwrapResponse<T>(resp: GetResponse): T {
return (resp as unknown) as T; return (resp as unknown) as T;
@ -19,13 +23,10 @@ export function unwrapResponse<T>(resp: GetResponse): T {
/** /**
* Gitlab API implementation of the `Remote` contract. * Gitlab API implementation of the `Remote` contract.
*/ */
export class GitlabRemote implements Remote { export class GitlabRemote extends BaseRemote<RemoteBundle, RemoteOptions> implements Remote {
protected client?: RemoteBundle;
protected options: RemoteOptions;
/* eslint-disable-next-line no-useless-constructor */
constructor(options: RemoteOptions) { constructor(options: RemoteOptions) {
this.options = options; super(options);
this.options.logger.debug(options, 'created gitlab remote'); this.options.logger.debug(options, 'created gitlab remote');
} }
@ -38,16 +39,35 @@ export class GitlabRemote implements Remote {
return true; return true;
} }
public async createComment(): Promise<void> { public async createComment(options: CommentUpdate): Promise<void> {
throw new NotImplementedError(); const project = await this.resolvePath(options.project);
const body = this.formatBody(options);
if (this.writeCapable) {
await this.writeClient.IssueNotes.create(project.projectId, parseInt(options.issue, 10), body);
}
} }
public async createLabel(): Promise<LabelUpdate> { public async createLabel(options: LabelUpdate): Promise<LabelUpdate> {
throw new NotImplementedError(); const project = await this.resolvePath(options.project);
if (this.writeCapable) {
await this.writeClient.Labels.create(project.projectId, options.name, '#' + options.color, {
description: options.desc,
});
}
return options;
} }
public async deleteLabel(): Promise<LabelUpdate> { public async deleteLabel(options: LabelUpdate): Promise<LabelUpdate> {
throw new NotImplementedError(); const project = await this.resolvePath(options.project);
if (this.writeCapable) {
await this.writeClient.Labels.remove(project.projectId, options.name);
}
return options;
} }
public async getIssue(): Promise<Array<IssueUpdate>> { public async getIssue(): Promise<Array<IssueUpdate>> {
@ -65,7 +85,7 @@ export class GitlabRemote implements Remote {
})); }));
return data.map((issue) => ({ return data.map((issue) => ({
issue: issue.id.toString(), issue: issue.iid.toString(),
labels: issue.labels, labels: issue.labels,
name: issue.title, name: issue.title,
project: options.project, project: options.project,
@ -77,19 +97,36 @@ export class GitlabRemote implements Remote {
const data = unwrapResponse<Array<GitlabLabel>>(await mustExist(this.client).Labels.all(project.projectId)); const data = unwrapResponse<Array<GitlabLabel>>(await mustExist(this.client).Labels.all(project.projectId));
return data.map((label) => ({ return data.map((label) => ({
color: label.color, color: label.color.replace(/^#/, ''),
desc: label.description, desc: label.description,
name: label.name, name: label.name,
project: options.project, project: options.project,
})); }));
} }
public async updateIssue(): Promise<IssueUpdate> { public async updateIssue(options: IssueUpdate): Promise<IssueUpdate> {
throw new NotImplementedError(); const project = await this.resolvePath(options.project);
if (this.writeCapable) {
await this.writeClient.Issues.edit(project.projectId, parseInt(options.issue, 10), {
labels: options.labels,
});
}
return options;
} }
public async updateLabel(): Promise<LabelUpdate> { public async updateLabel(options: LabelUpdate): Promise<LabelUpdate> {
throw new NotImplementedError(); const project = await this.resolvePath(options.project);
if (this.writeCapable) {
await this.writeClient.Labels.edit(project.projectId, options.name, {
color: '#' + options.color,
description: options.desc,
});
}
return options;
} }
public async resolvePath(path: string): Promise<{ public async resolvePath(path: string): Promise<{