From a94ce60ec57dd686291861c0cd4a481068890a62 Mon Sep 17 00:00:00 2001 From: selfisekai Date: Sun, 23 Aug 2020 13:16:38 +0200 Subject: [PATCH] initial issue replicating (gitlab) --- src/types.ts | 1 + src/vendor/gitlab/repomgr.ts | 33 +++++++++++++++++++++++++-------- src/vendor/gitlab/vendormgr.ts | 21 +++++++++++++++++++-- 3 files changed, 45 insertions(+), 10 deletions(-) diff --git a/src/types.ts b/src/types.ts index 7e23c23..2473338 100644 --- a/src/types.ts +++ b/src/types.ts @@ -53,6 +53,7 @@ export interface RepoManager { repo: Repo; initialize: () => Promise; getIssue: (id: string) => Promise; + replicateIssue?: (issue: Issue) => Promise; getMergeRequest: (id: string) => Promise; } diff --git a/src/vendor/gitlab/repomgr.ts b/src/vendor/gitlab/repomgr.ts index 21d93bf..c2dd07e 100644 --- a/src/vendor/gitlab/repomgr.ts +++ b/src/vendor/gitlab/repomgr.ts @@ -23,6 +23,7 @@ export default class GitHubRepoManager implements RepoManager { vendorMgr: GitLabVendorManager; repo: Repo; repoPath: string; + repoId: string; constructor(vendorMgr: GitLabVendorManager, repoPath: string) { this.vendorMgr = vendorMgr; @@ -43,17 +44,16 @@ export default class GitHubRepoManager implements RepoManager { name: repoSmallPath, }; this.repoPath = repoPath; + this.repoId = ''; // for strict null check, is replaced in .initialize } public async initialize() { - let meta = await this.vendorMgr._doRequest( + const meta = await this.vendorMgr._doRequest_gql( ` query ($path: ID!, $ownerStr: String!, $ownerID: ID!) { project(fullPath: $path) { + id path - namespace { - path - } } group(fullPath: $ownerID) { id @@ -73,8 +73,11 @@ export default class GitHubRepoManager implements RepoManager { ownerID: this.repo.owner.username, }, ); - assert(meta.project); - assert(meta.group || meta.user); + assert(meta.project, 'no project'); + assert(meta.group || meta.user, 'no top-level project owner'); + const [, repoId] = /\/(\d+)$/.exec(meta.project.id) || [,]; + assert(repoId, 'broken project id'); + this.repoId = repoId; this.repo.owner.username = meta.project.path; if (meta.group) { this.repo.owner.type = ACTOR_TYPE.ORG; @@ -85,7 +88,7 @@ export default class GitHubRepoManager implements RepoManager { } public async getIssue(number: string): Promise { - const resp = await this.vendorMgr._doRequest( + const resp = await this.vendorMgr._doRequest_gql( ` query ($path: ID!, $id: String!) { project(fullPath: $path) { @@ -119,8 +122,22 @@ export default class GitHubRepoManager implements RepoManager { }; } + public async replicateIssue(issue: Issue) { + // yes, v4, gitlab doesn't support creating issues with graphql api 🤦‍♀️ + const resp = await this.vendorMgr._doRequest_v4( + 'POST', + `projects/${encodeURIComponent(this.repoId)}/issues`, + { + title: issue.title, + description: issue.content, + }, + ); + assert(resp.iid); + return this.getIssue(resp.iid.toString()); + } + public async getMergeRequest(number: string): Promise { - const resp = await this.vendorMgr._doRequest( + const resp = await this.vendorMgr._doRequest_gql( ` query ($path: ID!, $id: String!) { project(fullPath: $path) { diff --git a/src/vendor/gitlab/vendormgr.ts b/src/vendor/gitlab/vendormgr.ts index 74afe60..dd37136 100644 --- a/src/vendor/gitlab/vendormgr.ts +++ b/src/vendor/gitlab/vendormgr.ts @@ -7,6 +7,7 @@ */ import got from 'got'; +import qs from 'querystring'; import { VendorManager, VENDOR_TYPE, Vendor, RepoManager } from '../../types'; import { GLQuery } from './api-types'; import GitLabRepoManager from './repomgr'; @@ -20,6 +21,8 @@ export interface GitLabConfig { export default class GitLabVendorManager implements VendorManager { vendor: Vendor; config: GitLabConfig; + apiEndpoint: string; + v4Endpoint: string; gqlEndpoint: string; constructor(config: GitLabConfig) { @@ -29,7 +32,9 @@ export default class GitLabVendorManager implements VendorManager domain: config.domain, }; this.config = config; - this.gqlEndpoint = `https://${this.vendor.domain}/api/graphql`; + this.apiEndpoint = `https://${this.vendor.domain}/api`; + this.v4Endpoint = `${this.apiEndpoint}/v4`; + this.gqlEndpoint = `${this.apiEndpoint}/graphql`; } public async initialize() { @@ -41,7 +46,7 @@ export default class GitLabVendorManager implements VendorManager } /** internal and for RepoManager */ - public async _doRequest(query: string, variables: any) { + public async _doRequest_gql(query: string, variables: any) { return got .post(this.gqlEndpoint, { body: JSON.stringify({ query, variables }), @@ -53,4 +58,16 @@ export default class GitLabVendorManager implements VendorManager .then((res) => JSON.parse(res.body)) .then((res) => res.data) as Promise; } + + /** internal and for RepoManager */ + public async _doRequest_v4(method: 'GET' | 'POST', path: string, query?: any) { + // did you know that gitlab graphql api is fucked up + // and does not support some of the core functionality like creating issues? + return got(`${this.v4Endpoint}/${path}?${qs.stringify(query)}`, { + method, + headers: { + Authorization: `Bearer ${this.config.token}`, + }, + }).then((res) => JSON.parse(res.body)); + } }