Skip to content

Commit 713be65

Browse files
feat: add github graphql implementation (#1)
1 parent 25a9777 commit 713be65

File tree

13 files changed

+802
-1
lines changed

13 files changed

+802
-1
lines changed

.eslintignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
artifacts/
2+
node_modules/
3+
features/*.feature

.eslintrc.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
extends: screwdriver

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,4 @@ dist
128128
.yarn/build-state.yml
129129
.yarn/install-state.gz
130130
.pnp.*
131+
artifacts/

LICENSE

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
Copyright 2024 Yahoo Inc.
2+
All rights reserved.
3+
4+
Redistribution and use in source and binary forms, with or without
5+
modification, are permitted provided that the following conditions are met:
6+
* Redistributions of source code must retain the above copyright
7+
notice, this list of conditions and the following disclaimer.
8+
* Redistributions in binary form must reproduce the above copyright
9+
notice, this list of conditions and the following disclaimer in the
10+
documentation and/or other materials provided with the distribution.
11+
* Neither the name of the Yahoo! Inc. nor the
12+
names of its contributors may be used to endorse or promote products
13+
derived from this software without specific prior written permission.
14+
15+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18+
DISCLAIMED. IN NO EVENT SHALL YAHOO! INC. BE LIABLE FOR ANY
19+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

README.md

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,83 @@
11
# scm-github-graphql
2-
Module to query github graphql api
2+
[![Version][npm-image]][npm-url] ![Downloads][downloads-image] [![Build Status][status-image]][status-url] [![Open Issues][issues-image]][issues-url] ![License][license-image]
3+
4+
## Usage
5+
6+
```bash
7+
npm install screwdriver-scm-github-graphql
8+
```
9+
10+
### Initialization
11+
12+
The class interacts with (GitHub GraphQL API)[https://docs.github.com/en/enterprise-cloud@latest/graphql/overview/about-the-graphql-api]
13+
The following configuration is needed
14+
15+
| Parameter | Type | Default | Description |
16+
| :------------- | :---- | :-------------| :-------------|
17+
| config | Object | | Configuration Object |
18+
| config.graphQlUrl | String | https://api.github.com/graphql | Github GraphQL API Endpoint |
19+
```js
20+
const scm = new GithubScmGraphQL({
21+
graphQlUrl: 'https://api.github.com/graphql'
22+
});
23+
```
24+
25+
### Methods
26+
27+
#### getEnterpriseUserAccount
28+
Required parameters:
29+
30+
| Parameter | Type | Description |
31+
| :------------- | :---- | :-------------|
32+
| schema | Object | The schema object |
33+
| schema.slug | String | The github enterprise slug |
34+
| schema.login | String | The github user's login name |
35+
| schema.token | String | The github token to interact with the graphql api |
36+
37+
#### Expected Outcome
38+
39+
Gets the enterprise user account based on schema https://docs.github.com/en/enterprise-cloud@latest/graphql/reference/objects#enterpriseuseraccount
40+
41+
#### listEnterpriseMembers
42+
Required parameters:
43+
44+
| Parameter | Type | Description |
45+
| :------------- | :---- | :-------------|
46+
| schema | Object | The schema object |
47+
| schema.slug | String | The github enterprise slug |
48+
| schema.token | String | The github token to interact with the graphql api |
49+
50+
#### Expected Outcome
51+
52+
This method retrieves a list of enterprise members based on schema https://docs.github.com/en/enterprise-cloud@latest/graphql/reference/unions#enterprisemember.
53+
54+
##### getUser
55+
Required parameters:
56+
57+
| Parameter | Type | Description |
58+
| :------------- | :---- | :-------------|
59+
| schema | Object | The schema object |
60+
| schema.login | String | The github user's login name |
61+
| schema.token | String | The github token to interact with the graphql api |
62+
63+
##### Expected Outcome
64+
Returns the github user based on schema https://docs.github.com/en/enterprise-cloud@latest/graphql/reference/objects#user
65+
66+
## Testing
67+
68+
```bash
69+
npm test
70+
```
71+
72+
## License
73+
74+
Code licensed under the BSD 3-Clause license. See LICENSE file for terms.
75+
76+
[npm-image]: https://img.shields.io/npm/v/screwdriver-scm-github-graphql.svg
77+
[npm-url]: https://npmjs.org/package/screwdriver-scm-github-graphql
78+
[downloads-image]: https://img.shields.io/npm/dt/screwdriver-scm-github-graphql.svg
79+
[license-image]: https://img.shields.io/npm/l/screwdriver-scm-github-graphql.svg
80+
[issues-image]: https://img.shields.io/github/issues/screwdriver-cd/screwdriver.svg
81+
[issues-url]: https://github.com/screwdriver-cd/screwdriver/issues
82+
[status-image]: https://cd.screwdriver.cd/pipelines/13562/badge
83+
[status-url]: https://cd.screwdriver.cd/pipelines/13562

index.js

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
'use strict';
2+
3+
const SDGraphQLClient = require('./sd-graphql');
4+
const queries = require('./queries');
5+
6+
class GithubScmGraphQL {
7+
/**
8+
* constructor
9+
* @param {Object} config The config object
10+
* @param {String} config.graphQlUrl The graphql url
11+
*/
12+
constructor(config) {
13+
this.sdGql = new SDGraphQLClient({
14+
graphqlUrl: config.graphQlUrl || 'https://api.github.com/graphql'
15+
});
16+
}
17+
18+
/**
19+
* Gets the enterprise user account schema
20+
* @param {String} config The config object
21+
* @param {String} config.slug The github enterprise slug
22+
* @param {String} config.login The github user login
23+
* @param {String} config.token The access token
24+
* @returns Object https://docs.github.com/en/enterprise-cloud@latest/graphql/reference/objects#enterpriseuseraccount
25+
*/
26+
async getEnterpriseUserAccount(config) {
27+
const { slug, login, token } = config;
28+
29+
const { data } = await this.sdGql.query({
30+
query: queries.GetEnterpriseUserAccount,
31+
variables: { slug, query: login },
32+
token
33+
});
34+
35+
if (data && data.enterprise) {
36+
const { members } = data.enterprise;
37+
38+
if (members && members.totalCount === 1) {
39+
return members.nodes[0];
40+
}
41+
}
42+
43+
return null;
44+
}
45+
46+
/**
47+
* Helper method to paginate the enterprise members recursively
48+
* @param {*} config The config object
49+
* @param {*} cursor The current page
50+
* @param {*} members The list of members
51+
* @returns Array https://docs.github.com/en/enterprise-cloud@latest/graphql/reference/unions#enterprisemember
52+
*/
53+
async _listEnterpriseMembersHelper(config, cursor, allMembers = []) {
54+
const { slug, token } = config;
55+
56+
const { data } = await this.sdGql.query({
57+
query: queries.ListEnterpriseMembers,
58+
variables: { slug, cursor },
59+
token
60+
});
61+
62+
if (data && data.enterprise && data.enterprise.members) {
63+
const { nodes, pageInfo } = data.enterprise.members;
64+
65+
if (nodes) {
66+
allMembers.push(...nodes);
67+
}
68+
if (pageInfo && pageInfo.hasNextPage) {
69+
return this._listEnterpriseMembersHelper(config, pageInfo.endCursor, allMembers);
70+
}
71+
}
72+
73+
return allMembers;
74+
}
75+
76+
/**
77+
* List of enterprise members schema
78+
* @param {String} config The config object
79+
* @param {String} config.slug The github enterprise slug
80+
* @param {String} config.token The access token
81+
* @returns Array https://docs.github.com/en/enterprise-cloud@latest/graphql/reference/unions#enterprisemember
82+
*/
83+
async listEnterpriseMembers(config) {
84+
return this._listEnterpriseMembersHelper(config, null, []);
85+
}
86+
87+
/**
88+
* Gets the the github user schema
89+
* @param {Object} config The config object
90+
* @param {String} config.login The github user login
91+
* @param {String} config.toke The access token
92+
* @returns Object https://docs.github.com/en/enterprise-cloud@latest/graphql/reference/objects#user
93+
* or https://docs.github.com/en/enterprise-cloud@latest/graphql/reference/objects#enterpriseuseraccount
94+
*/
95+
async getUser(config) {
96+
const { login, token } = config;
97+
const { data } = await this.sdGql.query({
98+
query: queries.GetUser,
99+
variables: { login },
100+
token
101+
});
102+
103+
return data.user;
104+
}
105+
}
106+
107+
module.exports = GithubScmGraphQL;

mocha.config.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"reporterEnabled": "spec, mocha-sonarqube-reporter",
3+
"mochaSonarqubeReporterReporterOptions": {
4+
"output": "./artifacts/report/test.xml"
5+
}
6+
}

package.json

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"name": "screwdriver-scm-github-graphql",
3+
"version": "1.0.0",
4+
"description": "Github GraphQL SCM for Screwdriver",
5+
"main": "index.js",
6+
"scripts": {
7+
"pretest": "eslint .",
8+
"test": "nyc --report-dir ./artifacts/coverage --reporter=lcov mocha --reporter mocha-multi-reporters --reporter-options configFile=./mocha.config.json --recursive --timeout 4000 --retries 1 --exit --allow-uncaught true --color true"
9+
},
10+
"repository": {
11+
"type": "git",
12+
"url": "git+https://github.com/screwdriver-cd/scm-github-graphql.git"
13+
},
14+
"homepage": "https://github.com/screwdriver-cd/scm-github-graphql",
15+
"bugs": "https://github.com/screwdriver-cd/screwdriver/issues",
16+
"keywords": [
17+
"screwdriver",
18+
"yahoo"
19+
],
20+
"license": "BSD-3-Clause",
21+
"author": "Pritam Paul <pritamstyz4ever@gmail.com>",
22+
"contributors": [],
23+
"devDependencies": {
24+
"chai": "^4.3.6",
25+
"eslint": "^7.32.0",
26+
"eslint-config-screwdriver": "^5.0.1",
27+
"mocha": "^10.3.0",
28+
"mocha-multi-reporters": "^1.5.1",
29+
"mocha-sonarqube-reporter": "^1.0.2",
30+
"nyc": "^15.0.0",
31+
"sinon": "^9.0.0"
32+
},
33+
"dependencies": {
34+
"graphql-tag": "^2.12.6",
35+
"rewire": "^7.0.0",
36+
"rewiremock": "^3.14.5",
37+
"screwdriver-request": "^2.0.1"
38+
},
39+
"release": {
40+
"debug": false
41+
}
42+
}

queries.js

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
'use strict';
2+
3+
const gql = require('graphql-tag');
4+
5+
module.exports.GetEnterpriseUserAccount = gql`
6+
query GetEnterpriseUserAccount($slug: String!, $query: String!) {
7+
enterprise(slug: $slug) {
8+
name
9+
id
10+
members(query: $query, first: 1, role: MEMBER) {
11+
totalCount
12+
nodes {
13+
type: __typename
14+
... on EnterpriseUserAccount {
15+
id
16+
name
17+
login
18+
}
19+
... on User {
20+
id
21+
name
22+
login
23+
}
24+
}
25+
}
26+
}
27+
}
28+
`;
29+
30+
module.exports.ListEnterpriseMembers = gql`
31+
query ListEnterpriseMembers($slug: String!, $cursor: String) {
32+
enterprise(slug: $slug) {
33+
name
34+
id
35+
members(first: 100, role: MEMBER, after: $cursor) {
36+
totalCount
37+
pageInfo {
38+
endCursor
39+
hasNextPage
40+
}
41+
nodes {
42+
type: __typename
43+
... on EnterpriseUserAccount {
44+
id
45+
name
46+
login
47+
}
48+
... on User {
49+
id
50+
name
51+
login
52+
}
53+
}
54+
}
55+
organizations(first: 100) {
56+
totalCount
57+
pageInfo {
58+
endCursor
59+
hasNextPage
60+
}
61+
nodes {
62+
... on Organization {
63+
name
64+
id
65+
login
66+
}
67+
}
68+
}
69+
}
70+
}
71+
`;
72+
73+
module.exports.GetUser = gql`
74+
query GetUser($login: String!) {
75+
user(login: $login) {
76+
name
77+
id
78+
enterprises(first: 100) {
79+
totalCount
80+
pageInfo {
81+
endCursor
82+
hasNextPage
83+
}
84+
nodes {
85+
id
86+
name
87+
slug
88+
}
89+
}
90+
organizations(first: 100) {
91+
totalCount
92+
pageInfo {
93+
endCursor
94+
hasNextPage
95+
}
96+
nodes {
97+
id
98+
name
99+
login
100+
}
101+
}
102+
}
103+
}
104+
`;

0 commit comments

Comments
 (0)