Skip to content

Commit 78a431d

Browse files
committed
partial refactor, tests, and vscode config
1 parent d3d5632 commit 78a431d

12 files changed

Lines changed: 3857 additions & 223 deletions

File tree

.env.sample

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
GITHUB_TOKEN="gh123abc"

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
node_modules
2+
.env

.vscode/launch.json

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
// Use IntelliSense to learn about possible attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"type": "node",
9+
"request": "launch",
10+
"name": "--version",
11+
"skipFiles": [
12+
"<node_internals>/**"
13+
],
14+
"program": "${workspaceFolder}/github.js",
15+
"args": [
16+
"--version"
17+
]
18+
},
19+
{
20+
"type": "node",
21+
"request": "launch",
22+
"name": "--help",
23+
"skipFiles": [
24+
"<node_internals>/**"
25+
],
26+
"program": "${workspaceFolder}/github.js",
27+
"args": [
28+
"--help"
29+
]
30+
},
31+
{
32+
"type": "node",
33+
"request": "launch",
34+
"name": "branch exists",
35+
"skipFiles": [
36+
"<node_internals>/**"
37+
],
38+
"program": "${workspaceFolder}/github.js",
39+
"args": [
40+
"branch",
41+
"--owner", "pirafrank",
42+
"--repo", "test-repo",
43+
"--branch", "main"
44+
],
45+
"envFile": "${workspaceFolder}/.env"
46+
}
47+
]
48+
}

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,14 @@ node github.js commit \
7272
--commitMessage 'stuff'
7373
```
7474

75+
## Tests
76+
77+
Create a `.env` file with your `GITHUB_TOKEN`, then run:
78+
79+
```sh
80+
npm test
81+
```
82+
7583
## License
7684

7785
MIT

dummy/file1.txt

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

dummy/file2.txt

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

github.js

Lines changed: 8 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -1,153 +1,12 @@
1-
const fs = require("fs");
2-
const { createClient, cacheExchange, fetchExchange } = require("@urql/core");
31
const yargs = require("yargs");
42
const CURRENT_VERSION = require("./package.json").version;
53

6-
const GITHUB_GRAPHQL_URL =
7-
process.env.GITHUB_GRAPHQL_URL || "https://api.github.com/graphql";
8-
9-
const githubToken = process.env.GITHUB_TOKEN;
10-
if (!githubToken) {
11-
throw new Error("ERROR: GITHUB_TOKEN environment variable not set.");
12-
}
13-
14-
const client = createClient({
15-
url: GITHUB_GRAPHQL_URL,
16-
exchanges: [cacheExchange, fetchExchange],
17-
fetchOptions: {
18-
headers: {
19-
Authorization: `Bearer ${githubToken}`,
20-
},
21-
},
22-
});
23-
24-
function arrayHasElements(array) {
25-
return (array && Array.isArray(array) && array.length > 0)
26-
}
27-
28-
function extractChangedOrDeletedFiles(changedFiles, deletedFiles) {
29-
const changedFilesExist = arrayHasElements(changedFiles);
30-
const deletedFilesExist = arrayHasElements(deletedFiles);
31-
32-
if (!changedFilesExist && !deletedFilesExist) {
33-
throw new Error("No files specified as changed or deleted. Quitting.");
34-
}
35-
36-
return {
37-
changedFiles: changedFilesExist ? changedFiles : [],
38-
deletedFiles: deletedFilesExist ? deletedFiles : [],
39-
}
40-
}
41-
42-
async function fetchBranchData(repoOwner, repoName, branchName) {
43-
const query = `
44-
query($owner: String!, $repo: String!, $branch: String!) {
45-
repository(owner: $owner, name: $repo) {
46-
ref(qualifiedName: $branch) {
47-
name,
48-
target {
49-
oid
50-
}
51-
}
52-
}
53-
}
54-
`;
55-
56-
const variables = {
57-
owner: repoOwner,
58-
repo: repoName,
59-
branch: branchName,
60-
};
61-
62-
try {
63-
const response = await client.query(query, variables);
64-
return response
65-
} catch (error) {
66-
console.error(`Error while trying to fetching data from API: ${error.message}`);
67-
throw error;
68-
}
69-
}
70-
71-
async function checkIfBranchExists(repoOwner, repoName, branchName) {
72-
const response = await fetchBranchData(repoOwner, repoName, branchName);
73-
// NB. if response.data.repository.ref is null the remote branch does not exist!
74-
return response?.data?.repository?.ref || null;
75-
}
76-
77-
async function getShaOfParentCommit(repoOwner, repoName, branchName) {
78-
const response = await fetchBranchData(repoOwner, repoName, branchName);
79-
return response?.data?.repository?.ref?.target?.oid || null;
80-
}
81-
82-
async function createCommitOnBranch(
83-
repoOwner, // Owner of the repository
84-
repoName, // Name of the repository
85-
branchName, // Name of the branch to commit to
86-
changedFiles, // Array of paths of new or modified files
87-
deletedFiles, // Array of paths of tracked deleted files
88-
commitMessage, // Mandatory commit message
89-
commitDescription = null // Optional commit description
90-
) {
91-
92-
const parentCommit = await getShaOfParentCommit(repoOwner, repoName, branchName);
93-
if (!parentCommit) {
94-
throw new Error("Could not get SHA of parent commit. Does the branch exist? Aborting.");
95-
}
96-
97-
const graphqlRequest = {
98-
query: `mutation ($input: CreateCommitOnBranchInput!) { createCommitOnBranch(input: $input) { commit { url } } }`,
99-
variables: {
100-
input: {
101-
branch: {
102-
repositoryNameWithOwner: repoOwner + "/" + repoName,
103-
branchName: branchName,
104-
},
105-
message: {
106-
headline: commitMessage,
107-
},
108-
fileChanges: {},
109-
expectedHeadOid: parentCommit,
110-
},
111-
},
112-
};
113-
114-
({ changedFiles, deletedFiles } = extractChangedOrDeletedFiles(changedFiles, deletedFiles));
115-
console.log("Changed files:", JSON.stringify(changedFiles, null, 2));
116-
console.log("Deleted files:", JSON.stringify(deletedFiles, null, 2));
117-
118-
if (!commitMessage) { throw new Error("No commit message provided. Aborting."); }
119-
120-
if (commitDescription) {
121-
graphqlRequest.variables.input.message.body = commitDescription;
122-
}
123-
124-
const changedFilesGraphqlArray = changedFiles.map((file_path) => {
125-
const contents = fs.readFileSync(file_path, { encoding: "base64" });
126-
return { path: file_path, contents: contents };
127-
});
128-
if (changedFilesGraphqlArray && changedFilesGraphqlArray.length > 0) {
129-
graphqlRequest.variables.input.fileChanges.additions = changedFilesGraphqlArray;
130-
}
131-
132-
const deletedFilesGraphqlArray = deletedFiles.map((file_path) => {
133-
return { path: file_path };
134-
});
135-
if (deletedFilesGraphqlArray && deletedFilesGraphqlArray.length > 0) {
136-
graphqlRequest.variables.input.fileChanges.deletions = deletedFilesGraphqlArray;
137-
}
138-
139-
try {
140-
const response = await client
141-
.mutation(graphqlRequest.query, graphqlRequest.variables)
142-
.toPromise();
143-
return response;
144-
} catch (error) {
145-
console.error(`Error while performing commit action via GraphQL API: ${error.message}`);
146-
throw error;
147-
}
148-
}
149-
150-
module.exports = createCommitOnBranch;
4+
const {
5+
init,
6+
extractChangedOrDeletedFiles,
7+
createCommitOnBranch,
8+
checkIfBranchExists,
9+
} = require("./index");
15110

15211
yargs
15312
.command(
@@ -208,6 +67,7 @@ yargs
20867
commitDescription,
20968
} = argv;
21069

70+
init();
21171
createCommitOnBranch(
21272
owner,
21373
repo,
@@ -248,6 +108,7 @@ yargs
248108
},
249109
(argv) => {
250110
const { owner, repo, branch } = argv;
111+
init();
251112
checkIfBranchExists(owner, repo, branch)
252113
.then((response) => {
253114
const n = response ? "a" : "no";

0 commit comments

Comments
 (0)