@ffflorian/auto-merge 1.2.1 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AutoMerge.d.ts +2 -1
- package/dist/AutoMerge.js +33 -20
- package/package.json +3 -4
- package/dist/AutoMerge.test.d.ts +0 -1
- package/dist/AutoMerge.test.js +0 -109
package/dist/AutoMerge.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { AutoMergeConfig, ActionResult, Repository, RepositoryResult } from './types/index.js';
|
|
2
2
|
export declare class AutoMerge {
|
|
3
|
-
private readonly
|
|
3
|
+
private readonly baseHeaders;
|
|
4
4
|
private readonly config;
|
|
5
5
|
private readonly logger;
|
|
6
|
+
private readonly baseURL;
|
|
6
7
|
constructor(config: AutoMergeConfig);
|
|
7
8
|
private checkConfig;
|
|
8
9
|
private checkRepositorySlug;
|
package/dist/AutoMerge.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import axios from 'axios';
|
|
4
3
|
import logdown from 'logdown';
|
|
5
4
|
const __dirname = import.meta.dirname;
|
|
6
5
|
const packageJsonPath = path.join(__dirname, '../package.json');
|
|
@@ -14,14 +13,12 @@ export class AutoMerge {
|
|
|
14
13
|
markdown: false,
|
|
15
14
|
});
|
|
16
15
|
this.logger.state.isEnabled = true;
|
|
17
|
-
this.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
},
|
|
24
|
-
});
|
|
16
|
+
this.baseURL = 'https://api.github.com';
|
|
17
|
+
this.baseHeaders = {
|
|
18
|
+
Accept: 'application/vnd.github+json',
|
|
19
|
+
Authorization: `token ${this.config.authToken}`,
|
|
20
|
+
'User-Agent': `${toolName} v${toolVersion}`,
|
|
21
|
+
};
|
|
25
22
|
this.checkConfig(this.config);
|
|
26
23
|
}
|
|
27
24
|
checkConfig(config) {
|
|
@@ -67,9 +64,12 @@ export class AutoMerge {
|
|
|
67
64
|
return matchingRepositories;
|
|
68
65
|
}
|
|
69
66
|
async isPullRequestMergeable(repositorySlug, pullNumber) {
|
|
70
|
-
const resourceUrl = `/repos/${repositorySlug}/pulls/${pullNumber}
|
|
71
|
-
const response = await this.
|
|
72
|
-
|
|
67
|
+
const resourceUrl = new URL(`/repos/${repositorySlug}/pulls/${pullNumber}`, this.baseURL);
|
|
68
|
+
const response = await fetch(resourceUrl, { headers: this.baseHeaders });
|
|
69
|
+
if (!response.ok) {
|
|
70
|
+
throw new Error(`Error while checking merge request: ${response.statusText}`);
|
|
71
|
+
}
|
|
72
|
+
return (await response.json()).mergeable_state === 'clean';
|
|
73
73
|
}
|
|
74
74
|
async mergeByMatch(regex, repositories) {
|
|
75
75
|
const allRepositories = repositories || (await this.getRepositoriesWithOpenPullRequests());
|
|
@@ -137,18 +137,31 @@ export class AutoMerge {
|
|
|
137
137
|
}
|
|
138
138
|
/** @see https://docs.github.com/en/rest/reference/pulls#create-a-review-for-a-pull-request */
|
|
139
139
|
async postReview(repositorySlug, pullNumber) {
|
|
140
|
-
const resourceUrl = `/repos/${repositorySlug}/pulls/${pullNumber}/reviews
|
|
141
|
-
|
|
140
|
+
const resourceUrl = new URL(`/repos/${repositorySlug}/pulls/${pullNumber}/reviews`, this.baseURL);
|
|
141
|
+
resourceUrl.search = new URLSearchParams({ event: 'APPROVE' }).toString();
|
|
142
|
+
const response = await fetch(resourceUrl, { headers: this.baseHeaders, method: 'POST' });
|
|
143
|
+
if (!response.ok) {
|
|
144
|
+
throw new Error(`Error while approving pull request: ${response.statusText}`);
|
|
145
|
+
}
|
|
142
146
|
}
|
|
143
147
|
/** @see https://docs.github.com/en/rest/reference/issues#create-an-issue-comment */
|
|
144
148
|
async putMerge(repositorySlug, pullNumber, squash) {
|
|
145
|
-
const resourceUrl = `/repos/${repositorySlug}/pulls/${pullNumber}/merge
|
|
146
|
-
|
|
149
|
+
const resourceUrl = new URL(`/repos/${repositorySlug}/pulls/${pullNumber}/merge`, this.baseURL);
|
|
150
|
+
if (squash) {
|
|
151
|
+
resourceUrl.search = new URLSearchParams({ merge_method: 'squash' }).toString();
|
|
152
|
+
}
|
|
153
|
+
const response = await fetch(resourceUrl, { headers: this.baseHeaders, method: 'PUT' });
|
|
154
|
+
if (!response.ok) {
|
|
155
|
+
throw new Error(`Error while merging pull request: ${response.statusText}`);
|
|
156
|
+
}
|
|
147
157
|
}
|
|
148
158
|
async getPullRequestsBySlug(repositorySlug) {
|
|
149
|
-
const resourceUrl = `/repos/${repositorySlug}/pulls
|
|
150
|
-
|
|
151
|
-
const response = await
|
|
152
|
-
|
|
159
|
+
const resourceUrl = new URL(`/repos/${repositorySlug}/pulls`, this.baseURL);
|
|
160
|
+
resourceUrl.search = new URLSearchParams({ per_page: '100', state: 'open' }).toString();
|
|
161
|
+
const response = await fetch(resourceUrl, { headers: this.baseHeaders });
|
|
162
|
+
if (!response.ok) {
|
|
163
|
+
throw new Error(`Error while fetching pull requests: ${response.statusText}`);
|
|
164
|
+
}
|
|
165
|
+
return response.json();
|
|
153
166
|
}
|
|
154
167
|
}
|
package/package.json
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
"author": "Florian Imdahl <git@ffflorian.de>",
|
|
3
3
|
"bin": "dist/cli.js",
|
|
4
4
|
"dependencies": {
|
|
5
|
-
"axios": "1.13.2",
|
|
6
5
|
"commander": "14.0.2",
|
|
7
6
|
"cosmiconfig": "9.0.0",
|
|
8
7
|
"logdown": "3.3.1"
|
|
@@ -32,13 +31,13 @@
|
|
|
32
31
|
"name": "@ffflorian/auto-merge",
|
|
33
32
|
"repository": "https://github.com/ffflorian/node-packages/tree/main/packages/auto-merge",
|
|
34
33
|
"scripts": {
|
|
35
|
-
"build": "tsc -p tsconfig.json",
|
|
34
|
+
"build": "tsc -p tsconfig.build.json",
|
|
36
35
|
"clean": "rimraf dist",
|
|
37
36
|
"dist": "yarn clean && yarn build",
|
|
38
37
|
"start": "tsx src/cli.ts",
|
|
39
38
|
"test": "vitest run"
|
|
40
39
|
},
|
|
41
40
|
"type": "module",
|
|
42
|
-
"version": "1.
|
|
43
|
-
"gitHead": "
|
|
41
|
+
"version": "1.3.1",
|
|
42
|
+
"gitHead": "624bfac36e769ed7157fe9a9ada1c3e5443745ff"
|
|
44
43
|
}
|
package/dist/AutoMerge.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/AutoMerge.test.js
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { expect, describe, test, beforeEach, afterEach, vi } from 'vitest';
|
|
2
|
-
import nock from 'nock';
|
|
3
|
-
import { StatusCodes as HTTP_STATUS } from 'http-status-codes';
|
|
4
|
-
import { AutoMerge } from './AutoMerge.js';
|
|
5
|
-
describe('AutoMerge', () => {
|
|
6
|
-
describe('checkRepository', () => {
|
|
7
|
-
let autoMerge;
|
|
8
|
-
const validRepositoryNames = ['ffflorian/example-project-1', 'my-name/my_great-project42342'];
|
|
9
|
-
const repositories = [
|
|
10
|
-
{
|
|
11
|
-
pullRequests: [
|
|
12
|
-
{
|
|
13
|
-
draft: false,
|
|
14
|
-
head: {
|
|
15
|
-
ref: 'dependabot/npm_and_yarn/eslint-plugin-typescript-sort-keys-1.5.0',
|
|
16
|
-
sha: 'cd3ae10104a2ed9d937869b892457003ad68df74',
|
|
17
|
-
},
|
|
18
|
-
number: 253,
|
|
19
|
-
title: 'chore: bump eslint-plugin-typescript-sort-keys from 1.3.0 to 1.5.0',
|
|
20
|
-
},
|
|
21
|
-
],
|
|
22
|
-
repositorySlug: validRepositoryNames[0],
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
pullRequests: [
|
|
26
|
-
{
|
|
27
|
-
draft: false,
|
|
28
|
-
head: {
|
|
29
|
-
ref: 'dependabot/npm_and_yarn/typescript-4.0.3',
|
|
30
|
-
sha: 'e59a374b357763fab5d3e61b0fdab66f4746b097',
|
|
31
|
-
},
|
|
32
|
-
number: 252,
|
|
33
|
-
title: 'chore: bump typescript from 4.0.2 to 4.0.3',
|
|
34
|
-
},
|
|
35
|
-
],
|
|
36
|
-
repositorySlug: validRepositoryNames[1],
|
|
37
|
-
},
|
|
38
|
-
];
|
|
39
|
-
beforeEach(() => {
|
|
40
|
-
autoMerge = new AutoMerge({
|
|
41
|
-
authToken: 'example-token',
|
|
42
|
-
projects: {
|
|
43
|
-
gitHub: validRepositoryNames,
|
|
44
|
-
},
|
|
45
|
-
});
|
|
46
|
-
nock(autoMerge['apiClient'].defaults.baseURL)
|
|
47
|
-
.post(/^\/repos\/.+?\/.+?\/pulls\/\d+\/reviews\/?$/)
|
|
48
|
-
.reply(HTTP_STATUS.OK, { data: 'not-used' })
|
|
49
|
-
.persist();
|
|
50
|
-
nock(autoMerge['apiClient'].defaults.baseURL)
|
|
51
|
-
.get(/^\/repos\/.+?\/.+?\/pulls\/\d+\/?$/)
|
|
52
|
-
.reply(HTTP_STATUS.OK, { data: 'not-used' })
|
|
53
|
-
.persist();
|
|
54
|
-
nock(autoMerge['apiClient'].defaults.baseURL)
|
|
55
|
-
.put(/^\/repos\/.+?\/.+?\/pulls\/\d+\/merge\/?$/)
|
|
56
|
-
.reply(HTTP_STATUS.OK, { data: 'not-used' })
|
|
57
|
-
.persist();
|
|
58
|
-
});
|
|
59
|
-
afterEach(() => {
|
|
60
|
-
nock.cleanAll();
|
|
61
|
-
});
|
|
62
|
-
test('detects valid repository names', () => {
|
|
63
|
-
validRepositoryNames.forEach(repositoryName => {
|
|
64
|
-
const checkResult = autoMerge['checkRepositorySlug'](repositoryName);
|
|
65
|
-
expect(checkResult).toBe(true);
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
test('detects invalid repository names', () => {
|
|
69
|
-
const invalidRepositoryNames = [
|
|
70
|
-
'invalid-username--/valid-project-name',
|
|
71
|
-
'valid-username/invalid-project-name-',
|
|
72
|
-
'no-project-name',
|
|
73
|
-
'in(valid-username/valid-project-name',
|
|
74
|
-
'valid-username/invalid!project-name',
|
|
75
|
-
];
|
|
76
|
-
invalidRepositoryNames.forEach(repositoryName => {
|
|
77
|
-
const checkResult = autoMerge['checkRepositorySlug'](repositoryName);
|
|
78
|
-
expect(checkResult).toBe(false);
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
describe('getMatchingRepositories', () => {
|
|
82
|
-
test('matches repositories', () => {
|
|
83
|
-
const expectedESLint = [repositories[0]];
|
|
84
|
-
const actualESLint = autoMerge['getMatchingRepositories'](repositories, /eslint/gi);
|
|
85
|
-
expect(actualESLint).toEqual(expectedESLint);
|
|
86
|
-
const expectedTypeScript = [repositories[1]];
|
|
87
|
-
const actualTypeScript = autoMerge['getMatchingRepositories'](repositories, /typescript-4.0.3/gi);
|
|
88
|
-
expect(actualTypeScript).toEqual(expectedTypeScript);
|
|
89
|
-
const expectedAll = repositories;
|
|
90
|
-
const actualAll = autoMerge['getMatchingRepositories'](repositories, /typescript/gi);
|
|
91
|
-
expect(actualAll).toEqual(expectedAll);
|
|
92
|
-
const expectedNone = [];
|
|
93
|
-
const actualNone = autoMerge['getMatchingRepositories'](repositories, /no-match/gi);
|
|
94
|
-
expect(actualNone).toEqual(expectedNone);
|
|
95
|
-
});
|
|
96
|
-
});
|
|
97
|
-
describe('mergeByMatch', () => {
|
|
98
|
-
test('merge matching PRs', async () => {
|
|
99
|
-
vi.spyOn(autoMerge, 'putMerge');
|
|
100
|
-
await autoMerge.mergeByMatch(/eslint/gi, repositories);
|
|
101
|
-
const expectedRepositoryESLint = repositories[0];
|
|
102
|
-
expect(autoMerge['putMerge']).toHaveBeenCalledWith(expectedRepositoryESLint.repositorySlug, expectedRepositoryESLint.pullRequests[0].number, false);
|
|
103
|
-
await autoMerge.mergeByMatch(/typescript-4.0.3/gi, repositories);
|
|
104
|
-
const expectedRepositoryTypescript = repositories[1];
|
|
105
|
-
expect(autoMerge['putMerge']).toHaveBeenCalledWith(expectedRepositoryTypescript.repositorySlug, expectedRepositoryTypescript.pullRequests[0].number, false);
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
});
|