npm-cli-gh-issue-preparator 1.0.0
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/.env.example +0 -0
- package/.eslintrc.cjs +65 -0
- package/.github/CODEOWNERS +2 -0
- package/.github/workflows/commit-lint.yml +52 -0
- package/.github/workflows/configs/commitlint.config.js +27 -0
- package/.github/workflows/create-pr.yml +66 -0
- package/.github/workflows/empty-format-test-job.yml +28 -0
- package/.github/workflows/format.yml +25 -0
- package/.github/workflows/publish.yml +47 -0
- package/.github/workflows/test.yml +38 -0
- package/.github/workflows/umino-project.yml +191 -0
- package/.prettierignore +22 -0
- package/.prettierrc +5 -0
- package/CHANGELOG.md +27 -0
- package/CONTRIBUTING.md +107 -0
- package/README.md +49 -0
- package/bin/adapter/entry-points/cli/index.js +72 -0
- package/bin/adapter/entry-points/cli/index.js.map +1 -0
- package/bin/adapter/repositories/GitHubIssueRepository.js +340 -0
- package/bin/adapter/repositories/GitHubIssueRepository.js.map +1 -0
- package/bin/adapter/repositories/GitHubProjectRepository.js +123 -0
- package/bin/adapter/repositories/GitHubProjectRepository.js.map +1 -0
- package/bin/adapter/repositories/NodeLocalCommandRunner.js +34 -0
- package/bin/adapter/repositories/NodeLocalCommandRunner.js.map +1 -0
- package/bin/domain/entities/Issue.js +3 -0
- package/bin/domain/entities/Issue.js.map +1 -0
- package/bin/domain/entities/Project.js +3 -0
- package/bin/domain/entities/Project.js.map +1 -0
- package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js +37 -0
- package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js.map +1 -0
- package/bin/domain/usecases/StartPreparationUseCase.js +31 -0
- package/bin/domain/usecases/StartPreparationUseCase.js.map +1 -0
- package/bin/domain/usecases/adapter-interfaces/IssueRepository.js +3 -0
- package/bin/domain/usecases/adapter-interfaces/IssueRepository.js.map +1 -0
- package/bin/domain/usecases/adapter-interfaces/LocalCommandRunner.js +3 -0
- package/bin/domain/usecases/adapter-interfaces/LocalCommandRunner.js.map +1 -0
- package/bin/domain/usecases/adapter-interfaces/ProjectRepository.js +3 -0
- package/bin/domain/usecases/adapter-interfaces/ProjectRepository.js.map +1 -0
- package/bin/index.js +6 -0
- package/bin/index.js.map +1 -0
- package/commitlint.config.js +6 -0
- package/jest.config.js +33 -0
- package/package.json +75 -0
- package/renovate.json +37 -0
- package/src/adapter/entry-points/cli/index.integration.test.ts +143 -0
- package/src/adapter/entry-points/cli/index.test.ts +165 -0
- package/src/adapter/entry-points/cli/index.ts +110 -0
- package/src/adapter/repositories/GitHubIssueRepository.integration.test.ts +50 -0
- package/src/adapter/repositories/GitHubIssueRepository.test.ts +996 -0
- package/src/adapter/repositories/GitHubIssueRepository.ts +470 -0
- package/src/adapter/repositories/GitHubProjectRepository.test.ts +252 -0
- package/src/adapter/repositories/GitHubProjectRepository.ts +162 -0
- package/src/adapter/repositories/NodeLocalCommandRunner.test.ts +80 -0
- package/src/adapter/repositories/NodeLocalCommandRunner.ts +37 -0
- package/src/domain/entities/Issue.ts +7 -0
- package/src/domain/entities/Project.ts +7 -0
- package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.test.ts +109 -0
- package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.ts +48 -0
- package/src/domain/usecases/StartPreparationUseCase.test.ts +150 -0
- package/src/domain/usecases/StartPreparationUseCase.ts +48 -0
- package/src/domain/usecases/adapter-interfaces/IssueRepository.ts +8 -0
- package/src/domain/usecases/adapter-interfaces/LocalCommandRunner.ts +7 -0
- package/src/domain/usecases/adapter-interfaces/ProjectRepository.ts +5 -0
- package/src/index.test.ts +7 -0
- package/src/index.ts +3 -0
- package/tsconfig.build.json +11 -0
- package/tsconfig.json +16 -0
- package/types/adapter/entry-points/cli/index.d.ts +5 -0
- package/types/adapter/entry-points/cli/index.d.ts.map +1 -0
- package/types/adapter/repositories/GitHubIssueRepository.d.ts +14 -0
- package/types/adapter/repositories/GitHubIssueRepository.d.ts.map +1 -0
- package/types/adapter/repositories/GitHubProjectRepository.d.ts +9 -0
- package/types/adapter/repositories/GitHubProjectRepository.d.ts.map +1 -0
- package/types/adapter/repositories/NodeLocalCommandRunner.d.ts +9 -0
- package/types/adapter/repositories/NodeLocalCommandRunner.d.ts.map +1 -0
- package/types/domain/entities/Issue.d.ts +8 -0
- package/types/domain/entities/Issue.d.ts.map +1 -0
- package/types/domain/entities/Project.d.ts +8 -0
- package/types/domain/entities/Project.d.ts.map +1 -0
- package/types/domain/usecases/NotifyFinishedIssuePreparationUseCase.d.ts +20 -0
- package/types/domain/usecases/NotifyFinishedIssuePreparationUseCase.d.ts.map +1 -0
- package/types/domain/usecases/StartPreparationUseCase.d.ts +17 -0
- package/types/domain/usecases/StartPreparationUseCase.d.ts.map +1 -0
- package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts +8 -0
- package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts.map +1 -0
- package/types/domain/usecases/adapter-interfaces/LocalCommandRunner.d.ts +8 -0
- package/types/domain/usecases/adapter-interfaces/LocalCommandRunner.d.ts.map +1 -0
- package/types/domain/usecases/adapter-interfaces/ProjectRepository.d.ts +5 -0
- package/types/domain/usecases/adapter-interfaces/ProjectRepository.d.ts.map +1 -0
- package/types/index.d.ts +3 -0
- package/types/index.d.ts.map +1 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GitHubProjectRepository = void 0;
|
|
4
|
+
function isGitHubApiResponse(value) {
|
|
5
|
+
if (typeof value !== 'object' || value === null)
|
|
6
|
+
return false;
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
class GitHubProjectRepository {
|
|
10
|
+
constructor(token) {
|
|
11
|
+
this.token = token;
|
|
12
|
+
}
|
|
13
|
+
parseGitHubProjectUrl(url) {
|
|
14
|
+
const orgMatch = url.match(/github\.com\/orgs\/([^/]+)\/projects\/(\d+)/);
|
|
15
|
+
if (orgMatch) {
|
|
16
|
+
return {
|
|
17
|
+
owner: orgMatch[1],
|
|
18
|
+
projectNumber: orgMatch[2],
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
const userMatch = url.match(/github\.com\/users\/([^/]+)\/projects\/(\d+)/);
|
|
22
|
+
if (userMatch) {
|
|
23
|
+
return {
|
|
24
|
+
owner: userMatch[1],
|
|
25
|
+
projectNumber: userMatch[2],
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
const repoMatch = url.match(/github\.com\/([^/]+)\/([^/]+)\/projects\/(\d+)/);
|
|
29
|
+
if (repoMatch) {
|
|
30
|
+
return {
|
|
31
|
+
owner: repoMatch[1],
|
|
32
|
+
projectNumber: repoMatch[3],
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
throw new Error(`Invalid GitHub project URL: ${url}`);
|
|
36
|
+
}
|
|
37
|
+
async getByUrl(url) {
|
|
38
|
+
const { owner, projectNumber } = this.parseGitHubProjectUrl(url);
|
|
39
|
+
const projectQuery = `
|
|
40
|
+
query($owner: String!, $number: Int!) {
|
|
41
|
+
organization(login: $owner) {
|
|
42
|
+
projectV2(number: $number) {
|
|
43
|
+
id
|
|
44
|
+
title
|
|
45
|
+
url
|
|
46
|
+
fields(first: 100) {
|
|
47
|
+
nodes {
|
|
48
|
+
... on ProjectV2SingleSelectField {
|
|
49
|
+
name
|
|
50
|
+
options {
|
|
51
|
+
name
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
... on ProjectV2Field {
|
|
55
|
+
name
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
user(login: $owner) {
|
|
62
|
+
projectV2(number: $number) {
|
|
63
|
+
id
|
|
64
|
+
title
|
|
65
|
+
url
|
|
66
|
+
fields(first: 100) {
|
|
67
|
+
nodes {
|
|
68
|
+
... on ProjectV2SingleSelectField {
|
|
69
|
+
name
|
|
70
|
+
options {
|
|
71
|
+
name
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
... on ProjectV2Field {
|
|
75
|
+
name
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
`;
|
|
83
|
+
const response = await fetch('https://api.github.com/graphql', {
|
|
84
|
+
method: 'POST',
|
|
85
|
+
headers: {
|
|
86
|
+
Authorization: `Bearer ${this.token}`,
|
|
87
|
+
'Content-Type': 'application/json',
|
|
88
|
+
},
|
|
89
|
+
body: JSON.stringify({
|
|
90
|
+
query: projectQuery,
|
|
91
|
+
variables: {
|
|
92
|
+
owner,
|
|
93
|
+
number: parseInt(projectNumber, 10),
|
|
94
|
+
},
|
|
95
|
+
}),
|
|
96
|
+
});
|
|
97
|
+
if (!response.ok) {
|
|
98
|
+
const errorText = await response.text();
|
|
99
|
+
throw new Error(`GitHub API error: ${errorText}`);
|
|
100
|
+
}
|
|
101
|
+
const responseData = await response.json();
|
|
102
|
+
if (!isGitHubApiResponse(responseData)) {
|
|
103
|
+
throw new Error('Invalid API response format');
|
|
104
|
+
}
|
|
105
|
+
const result = responseData;
|
|
106
|
+
const project = result.data?.organization?.projectV2 || result.data?.user?.projectV2;
|
|
107
|
+
if (!project) {
|
|
108
|
+
throw new Error(`Project not found: ${url}`);
|
|
109
|
+
}
|
|
110
|
+
const fields = project.fields.nodes;
|
|
111
|
+
const statusField = fields.find((f) => f.name === 'Status');
|
|
112
|
+
const statuses = statusField?.options?.map((o) => o.name) || [];
|
|
113
|
+
return {
|
|
114
|
+
id: project.id,
|
|
115
|
+
url: project.url,
|
|
116
|
+
name: project.title,
|
|
117
|
+
statuses,
|
|
118
|
+
customFieldNames: fields.map((f) => f.name),
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
exports.GitHubProjectRepository = GitHubProjectRepository;
|
|
123
|
+
//# sourceMappingURL=GitHubProjectRepository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GitHubProjectRepository.js","sourceRoot":"","sources":["../../../src/adapter/repositories/GitHubProjectRepository.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NodeLocalCommandRunner = void 0;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const util_1 = require("util");
|
|
6
|
+
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
7
|
+
class NodeLocalCommandRunner {
|
|
8
|
+
async runCommand(command) {
|
|
9
|
+
try {
|
|
10
|
+
const { stdout, stderr } = await execAsync(command);
|
|
11
|
+
return {
|
|
12
|
+
stdout,
|
|
13
|
+
stderr,
|
|
14
|
+
exitCode: 0,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
if (error &&
|
|
19
|
+
typeof error === 'object' &&
|
|
20
|
+
'stdout' in error &&
|
|
21
|
+
'stderr' in error &&
|
|
22
|
+
'code' in error) {
|
|
23
|
+
return {
|
|
24
|
+
stdout: String(error.stdout),
|
|
25
|
+
stderr: String(error.stderr),
|
|
26
|
+
exitCode: typeof error.code === 'number' ? error.code : 1,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
throw error;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.NodeLocalCommandRunner = NodeLocalCommandRunner;
|
|
34
|
+
//# sourceMappingURL=NodeLocalCommandRunner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NodeLocalCommandRunner.js","sourceRoot":"","sources":["../../../src/adapter/repositories/NodeLocalCommandRunner.ts"],"names":[],"mappings":";;;AACA,iDAAqC;AACrC,+BAAiC;AAEjC,MAAM,SAAS,GAAG,IAAA,gBAAS,EAAC,oBAAI,CAAC,CAAC;AAElC,MAAa,sBAAsB;IACjC,KAAK,CAAC,UAAU,CAAC,OAAe;QAK9B,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC;YACpD,OAAO;gBACL,MAAM;gBACN,MAAM;gBACN,QAAQ,EAAE,CAAC;aACZ,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IACE,KAAK;gBACL,OAAO,KAAK,KAAK,QAAQ;gBACzB,QAAQ,IAAI,KAAK;gBACjB,QAAQ,IAAI,KAAK;gBACjB,MAAM,IAAI,KAAK,EACf,CAAC;gBACD,OAAO;oBACL,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;oBAC5B,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;oBAC5B,QAAQ,EAAE,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;iBAC1D,CAAC;YACJ,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;CACF;AA9BD,wDA8BC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Issue.js","sourceRoot":"","sources":["../../../src/domain/entities/Issue.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Project.js","sourceRoot":"","sources":["../../../src/domain/entities/Project.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NotifyFinishedIssuePreparationUseCase = exports.IllegalIssueStatusError = exports.IssueNotFoundError = void 0;
|
|
4
|
+
class IssueNotFoundError extends Error {
|
|
5
|
+
constructor(issueUrl) {
|
|
6
|
+
super(`Issue not found: ${issueUrl}`);
|
|
7
|
+
this.name = 'IssueNotFoundError';
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.IssueNotFoundError = IssueNotFoundError;
|
|
11
|
+
class IllegalIssueStatusError extends Error {
|
|
12
|
+
constructor(issueUrl, currentStatus, expectedStatus) {
|
|
13
|
+
super(`Illegal issue status for ${issueUrl}: expected ${expectedStatus}, but got ${currentStatus}`);
|
|
14
|
+
this.name = 'IllegalIssueStatusError';
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.IllegalIssueStatusError = IllegalIssueStatusError;
|
|
18
|
+
class NotifyFinishedIssuePreparationUseCase {
|
|
19
|
+
constructor(projectRepository, issueRepository) {
|
|
20
|
+
this.projectRepository = projectRepository;
|
|
21
|
+
this.issueRepository = issueRepository;
|
|
22
|
+
this.run = async (params) => {
|
|
23
|
+
const project = await this.projectRepository.getByUrl(params.projectUrl);
|
|
24
|
+
const issue = await this.issueRepository.get(params.issueUrl, project);
|
|
25
|
+
if (!issue) {
|
|
26
|
+
throw new IssueNotFoundError(params.issueUrl);
|
|
27
|
+
}
|
|
28
|
+
else if (issue.status !== params.preparationStatus) {
|
|
29
|
+
throw new IllegalIssueStatusError(params.issueUrl, issue.status, params.preparationStatus);
|
|
30
|
+
}
|
|
31
|
+
issue.status = params.awaitingQualityCheckStatus;
|
|
32
|
+
await this.issueRepository.update(issue, project);
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.NotifyFinishedIssuePreparationUseCase = NotifyFinishedIssuePreparationUseCase;
|
|
37
|
+
//# sourceMappingURL=NotifyFinishedIssuePreparationUseCase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NotifyFinishedIssuePreparationUseCase.js","sourceRoot":"","sources":["../../../src/domain/usecases/NotifyFinishedIssuePreparationUseCase.ts"],"names":[],"mappings":";;;AAGA,MAAa,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,QAAgB;QAC1B,KAAK,CAAC,oBAAoB,QAAQ,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AALD,gDAKC;AACD,MAAa,uBAAwB,SAAQ,KAAK;IAChD,YAAY,QAAgB,EAAE,aAAqB,EAAE,cAAsB;QACzE,KAAK,CACH,4BAA4B,QAAQ,cAAc,cAAc,aAAa,aAAa,EAAE,CAC7F,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAPD,0DAOC;AAED,MAAa,qCAAqC;IAChD,YACmB,iBAAoC,EACpC,eAAgC;QADhC,sBAAiB,GAAjB,iBAAiB,CAAmB;QACpC,oBAAe,GAAf,eAAe,CAAiB;QAGnD,QAAG,GAAG,KAAK,EAAE,MAKZ,EAAiB,EAAE;YAClB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAEzE,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAEvE,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,IAAI,kBAAkB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAChD,CAAC;iBAAM,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,iBAAiB,EAAE,CAAC;gBACrD,MAAM,IAAI,uBAAuB,CAC/B,MAAM,CAAC,QAAQ,EACf,KAAK,CAAC,MAAM,EACZ,MAAM,CAAC,iBAAiB,CACzB,CAAC;YACJ,CAAC;YAED,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,0BAA0B,CAAC;YACjD,MAAM,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACpD,CAAC,CAAC;IAxBC,CAAC;CAyBL;AA7BD,sFA6BC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StartPreparationUseCase = void 0;
|
|
4
|
+
class StartPreparationUseCase {
|
|
5
|
+
constructor(projectRepository, issueRepository, localCommandRunner) {
|
|
6
|
+
this.projectRepository = projectRepository;
|
|
7
|
+
this.issueRepository = issueRepository;
|
|
8
|
+
this.localCommandRunner = localCommandRunner;
|
|
9
|
+
this.maximumPreparingIssuesCount = 6;
|
|
10
|
+
this.run = async (params) => {
|
|
11
|
+
const project = await this.projectRepository.getByUrl(params.projectUrl);
|
|
12
|
+
const allIssues = await this.issueRepository.getAllOpened(project);
|
|
13
|
+
const awaitingWorkspaceIssues = allIssues.filter((issue) => issue.status === params.awaitingWorkspaceStatus);
|
|
14
|
+
if (allIssues.filter((issue) => issue.status === params.preparationStatus)
|
|
15
|
+
.length >= this.maximumPreparingIssuesCount) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
for (const issue of awaitingWorkspaceIssues) {
|
|
19
|
+
const agent = issue.labels
|
|
20
|
+
.find((label) => label.startsWith('category:'))
|
|
21
|
+
?.replace('category:', '')
|
|
22
|
+
.trim() || params.defaultAgentName;
|
|
23
|
+
issue.status = params.preparationStatus;
|
|
24
|
+
await this.issueRepository.update(issue, project);
|
|
25
|
+
await this.localCommandRunner.runCommand(`aw ${project.url} ${issue.url} ${agent}`);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.StartPreparationUseCase = StartPreparationUseCase;
|
|
31
|
+
//# sourceMappingURL=StartPreparationUseCase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StartPreparationUseCase.js","sourceRoot":"","sources":["../../../src/domain/usecases/StartPreparationUseCase.ts"],"names":[],"mappings":";;;AAIA,MAAa,uBAAuB;IAElC,YACmB,iBAAoC,EACpC,eAAgC,EAChC,kBAAsC;QAFtC,sBAAiB,GAAjB,iBAAiB,CAAmB;QACpC,oBAAe,GAAf,eAAe,CAAiB;QAChC,uBAAkB,GAAlB,kBAAkB,CAAoB;QAJzD,gCAA2B,GAAG,CAAC,CAAC;QAOhC,QAAG,GAAG,KAAK,EAAE,MAKZ,EAAiB,EAAE;YAClB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAEzE,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YAEnE,MAAM,uBAAuB,GAAG,SAAS,CAAC,MAAM,CAC9C,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,uBAAuB,CAC3D,CAAC;YAEF,IACE,SAAS,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,iBAAiB,CAAC;iBACnE,MAAM,IAAI,IAAI,CAAC,2BAA2B,EAC7C,CAAC;gBACD,OAAO;YACT,CAAC;YAED,KAAK,MAAM,KAAK,IAAI,uBAAuB,EAAE,CAAC;gBAC5C,MAAM,KAAK,GACT,KAAK,CAAC,MAAM;qBACT,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;oBAC/C,EAAE,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;qBACzB,IAAI,EAAE,IAAI,MAAM,CAAC,gBAAgB,CAAC;gBACvC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,iBAAiB,CAAC;gBACxC,MAAM,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;gBAElD,MAAM,IAAI,CAAC,kBAAkB,CAAC,UAAU,CACtC,MAAM,OAAO,CAAC,GAAG,IAAI,KAAK,CAAC,GAAG,IAAI,KAAK,EAAE,CAC1C,CAAC;YACJ,CAAC;QACH,CAAC,CAAC;IApCC,CAAC;CAqCL;AA3CD,0DA2CC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IssueRepository.js","sourceRoot":"","sources":["../../../../src/domain/usecases/adapter-interfaces/IssueRepository.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LocalCommandRunner.js","sourceRoot":"","sources":["../../../../src/domain/usecases/adapter-interfaces/LocalCommandRunner.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProjectRepository.js","sourceRoot":"","sources":["../../../../src/domain/usecases/adapter-interfaces/ProjectRepository.ts"],"names":[],"mappings":""}
|
package/bin/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.program = void 0;
|
|
4
|
+
const index_1 = require("./adapter/entry-points/cli/index");
|
|
5
|
+
Object.defineProperty(exports, "program", { enumerable: true, get: function () { return index_1.program; } });
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
package/bin/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,4DAA2D;AAElD,wFAFA,eAAO,OAEA"}
|
package/jest.config.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
preset: 'ts-jest',
|
|
3
|
+
testEnvironment: 'node',
|
|
4
|
+
transform: {
|
|
5
|
+
'^.+\\.ts?$': 'ts-jest',
|
|
6
|
+
},
|
|
7
|
+
transformIgnorePatterns: ['<rootDir>/node_modules/'],
|
|
8
|
+
collectCoverage: true,
|
|
9
|
+
collectCoverageFrom: [
|
|
10
|
+
'src/**/*.ts',
|
|
11
|
+
'!src/**/*.test.ts',
|
|
12
|
+
'!src/**/*.spec.ts',
|
|
13
|
+
'!src/**/adapter-interfaces/**',
|
|
14
|
+
],
|
|
15
|
+
coverageDirectory: 'reports/coverage',
|
|
16
|
+
coverageThreshold: {
|
|
17
|
+
global: {
|
|
18
|
+
branches: 100,
|
|
19
|
+
functions: 100,
|
|
20
|
+
lines: 100,
|
|
21
|
+
statements: 100,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
reporters: [
|
|
25
|
+
'default',
|
|
26
|
+
['jest-junit', { outputDirectory: 'reports/jest-junit' }],
|
|
27
|
+
[
|
|
28
|
+
'./node_modules/jest-html-reporter',
|
|
29
|
+
{ outputPath: 'reports/jest-html-reporter/index.html' },
|
|
30
|
+
],
|
|
31
|
+
],
|
|
32
|
+
testPathIgnorePatterns: ['/node_modules/', '/bin/', '/dist/'],
|
|
33
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "npm-cli-gh-issue-preparator",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "bin/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"prebuild": "npm run doctor",
|
|
8
|
+
"doctor:node-version": "check-node-version --node 25 --npx 11 --npm 11",
|
|
9
|
+
"doctor": "npm run doctor:node-version",
|
|
10
|
+
"prettier": "prettier --write '**/*'",
|
|
11
|
+
"lint:eslint": "eslint src",
|
|
12
|
+
"lint:bypasscheck:test-skip": "! grep -r '\\.skip\\|describe\\.skip\\|it\\.skip\\|test\\.skip' src --include='*.test.ts' --include='*.spec.ts'",
|
|
13
|
+
"lint:bypasscheck:disable-checks": "! grep -r 'eslint-disable\\|@ts-ignore\\|@ts-nocheck\\|prettier-ignore' src --include='*.ts' --include='*.js' --exclude-dir=node_modules",
|
|
14
|
+
"lint:bypasscheck": "npm run lint:bypasscheck:test-skip && npm run lint:bypasscheck:disable-checks",
|
|
15
|
+
"lint": "npm run lint:eslint && npm run lint:bypasscheck",
|
|
16
|
+
"lint-fix": "eslint src --fix",
|
|
17
|
+
"fmt": "npm run prettier && npm run lint-fix",
|
|
18
|
+
"build": "tsc -p ./tsconfig.build.json",
|
|
19
|
+
"test": "jest"
|
|
20
|
+
},
|
|
21
|
+
"bin": {
|
|
22
|
+
"npm-cli-gh-issue-preparator": "./bin/adapter/entry-points/cli/index.js"
|
|
23
|
+
},
|
|
24
|
+
"types": "types/index.d.ts",
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/HiromiShikata/npm-cli-gh-issue-preparator.git"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [],
|
|
30
|
+
"author": "",
|
|
31
|
+
"license": "ISC",
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/HiromiShikata/npm-cli-gh-issue-preparator/issues"
|
|
34
|
+
},
|
|
35
|
+
"release": {
|
|
36
|
+
"plugins": [
|
|
37
|
+
"@semantic-release/commit-analyzer",
|
|
38
|
+
"@semantic-release/release-notes-generator",
|
|
39
|
+
"@semantic-release/changelog",
|
|
40
|
+
"@semantic-release/npm"
|
|
41
|
+
],
|
|
42
|
+
"branches": [
|
|
43
|
+
"main"
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://github.com/HiromiShikata/npm-cli-gh-issue-preparator#readme",
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
49
|
+
"@semantic-release/commit-analyzer": "^13.0.0",
|
|
50
|
+
"@types/jest": "^30.0.0",
|
|
51
|
+
"@typescript-eslint/eslint-plugin": "^7.2.0",
|
|
52
|
+
"@typescript-eslint/parser": "^7.2.0",
|
|
53
|
+
"check-node-version": "^4.2.1",
|
|
54
|
+
"commitlint": "^20.0.0",
|
|
55
|
+
"conventional-changelog-conventionalcommits": "^9.0.0",
|
|
56
|
+
"eslint": "^8.57.0",
|
|
57
|
+
"eslint-plugin-import": "^2.29.1",
|
|
58
|
+
"eslint-plugin-jest": "^28.14.0",
|
|
59
|
+
"eslint-plugin-no-type-assertion": "^1.3.0",
|
|
60
|
+
"eslint-plugin-unused-imports": "^3.1.0",
|
|
61
|
+
"jest": "^30.0.0",
|
|
62
|
+
"jest-html-reporter": "^4.0.0",
|
|
63
|
+
"jest-junit": "^16.0.0",
|
|
64
|
+
"jest-mock-extended": "^4.0.0",
|
|
65
|
+
"prettier": "^3.2.5",
|
|
66
|
+
"semantic-release": "^25.0.0",
|
|
67
|
+
"ts-jest": "^29.1.2",
|
|
68
|
+
"typescript": "^5.4.2"
|
|
69
|
+
},
|
|
70
|
+
"dependencies": {
|
|
71
|
+
"@semantic-release/npm": "^13.0.0",
|
|
72
|
+
"commander": "^14.0.0",
|
|
73
|
+
"dotenv": "^16.4.5"
|
|
74
|
+
}
|
|
75
|
+
}
|
package/renovate.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
|
3
|
+
"extends": ["config:base"],
|
|
4
|
+
"automerge": true,
|
|
5
|
+
"platformAutomerge": true,
|
|
6
|
+
"rebaseWhen": "auto",
|
|
7
|
+
"prConcurrentLimit": 2,
|
|
8
|
+
"schedule": ["every weekend"],
|
|
9
|
+
"ignorePresets": [],
|
|
10
|
+
"dependencyDashboard": false,
|
|
11
|
+
"branchConcurrentLimit": 2,
|
|
12
|
+
"ignorePaths": ["**/generated/*", "**/_gen/*"],
|
|
13
|
+
"packageRules": [
|
|
14
|
+
{
|
|
15
|
+
"matchPackagePatterns": ["*"],
|
|
16
|
+
"matchUpdateTypes": ["minor", "patch"],
|
|
17
|
+
"groupName": "all non-major dependencies",
|
|
18
|
+
"groupSlug": "all-minor-patch"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"matchPackageNames": ["eslint"],
|
|
22
|
+
"allowedVersions": "<9.0.0"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"matchPackageNames": ["@typescript-eslint/eslint-plugin"],
|
|
26
|
+
"allowedVersions": "<6.0.0"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"matchPackageNames": ["@typescript-eslint/parser"],
|
|
30
|
+
"allowedVersions": "<6.0.0"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"matchPackageNames": ["eslint-plugin-unused-imports"],
|
|
34
|
+
"allowedVersions": "<4.0.0"
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import dotenv from 'dotenv';
|
|
3
|
+
import { GitHubIssueRepository } from '../../repositories/GitHubIssueRepository';
|
|
4
|
+
import { GitHubProjectRepository } from '../../repositories/GitHubProjectRepository';
|
|
5
|
+
|
|
6
|
+
dotenv.config();
|
|
7
|
+
|
|
8
|
+
describe('index', () => {
|
|
9
|
+
const token = process.env.GH_TOKEN;
|
|
10
|
+
const projectUrl = 'https://github.com/users/HiromiShikata/projects/49';
|
|
11
|
+
const startDaemonIssueUrl =
|
|
12
|
+
'https://github.com/HiromiShikata/test-repository/issues/1552';
|
|
13
|
+
const notifyFinishedIssueUrl =
|
|
14
|
+
'https://github.com/HiromiShikata/test-repository/issues/1557';
|
|
15
|
+
|
|
16
|
+
describe('startDaemon', () => {
|
|
17
|
+
beforeAll(async () => {
|
|
18
|
+
if (!token) {
|
|
19
|
+
throw new Error('GH_TOKEN environment variable is required');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const issueRepository = new GitHubIssueRepository(token);
|
|
23
|
+
const projectRepository = new GitHubProjectRepository(token);
|
|
24
|
+
const project = await projectRepository.getByUrl(projectUrl);
|
|
25
|
+
|
|
26
|
+
const issue = await issueRepository.get(startDaemonIssueUrl, project);
|
|
27
|
+
if (!issue) {
|
|
28
|
+
throw new Error('Failed to get issue');
|
|
29
|
+
}
|
|
30
|
+
issue.status = 'Awaiting workspace';
|
|
31
|
+
await issueRepository.update(issue, project);
|
|
32
|
+
}, 60000);
|
|
33
|
+
|
|
34
|
+
afterAll(async () => {
|
|
35
|
+
if (!token) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const issueRepository = new GitHubIssueRepository(token);
|
|
40
|
+
const projectRepository = new GitHubProjectRepository(token);
|
|
41
|
+
const project = await projectRepository.getByUrl(projectUrl);
|
|
42
|
+
|
|
43
|
+
const issue = await issueRepository.get(startDaemonIssueUrl, project);
|
|
44
|
+
if (!issue) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
issue.status = 'Awaiting workspace';
|
|
48
|
+
await issueRepository.update(issue, project);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('success', async () => {
|
|
52
|
+
if (!token) {
|
|
53
|
+
throw new Error('GH_TOKEN environment variable is required');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const issueRepository = new GitHubIssueRepository(token);
|
|
57
|
+
const projectRepository = new GitHubProjectRepository(token);
|
|
58
|
+
const project = await projectRepository.getByUrl(projectUrl);
|
|
59
|
+
|
|
60
|
+
const beforeIssue = await issueRepository.get(
|
|
61
|
+
startDaemonIssueUrl,
|
|
62
|
+
project,
|
|
63
|
+
);
|
|
64
|
+
expect(beforeIssue?.status).toBe('Awaiting workspace');
|
|
65
|
+
|
|
66
|
+
const result = execSync(
|
|
67
|
+
'npx ts-node ./src/adapter/entry-points/cli/index.ts startDaemon --projectUrl https://github.com/users/HiromiShikata/projects/49 --awaitingWorkspaceStatus "Awaiting workspace" --preparationStatus "Preparation" --defaultAgentName "impl"',
|
|
68
|
+
{ encoding: 'utf-8', timeout: 600000 },
|
|
69
|
+
);
|
|
70
|
+
expect(result).toBeDefined();
|
|
71
|
+
|
|
72
|
+
const afterIssue = await issueRepository.get(
|
|
73
|
+
startDaemonIssueUrl,
|
|
74
|
+
project,
|
|
75
|
+
);
|
|
76
|
+
expect(afterIssue?.status).toBe('Preparation');
|
|
77
|
+
}, 600000);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
describe('notifyFinishedIssuePreparation', () => {
|
|
81
|
+
beforeAll(async () => {
|
|
82
|
+
if (!token) {
|
|
83
|
+
throw new Error('GH_TOKEN environment variable is required');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const issueRepository = new GitHubIssueRepository(token);
|
|
87
|
+
const projectRepository = new GitHubProjectRepository(token);
|
|
88
|
+
const project = await projectRepository.getByUrl(projectUrl);
|
|
89
|
+
|
|
90
|
+
const issue = await issueRepository.get(notifyFinishedIssueUrl, project);
|
|
91
|
+
if (!issue) {
|
|
92
|
+
throw new Error('Failed to get issue');
|
|
93
|
+
}
|
|
94
|
+
issue.status = 'Preparation';
|
|
95
|
+
await issueRepository.update(issue, project);
|
|
96
|
+
}, 60000);
|
|
97
|
+
|
|
98
|
+
afterAll(async () => {
|
|
99
|
+
if (!token) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const issueRepository = new GitHubIssueRepository(token);
|
|
104
|
+
const projectRepository = new GitHubProjectRepository(token);
|
|
105
|
+
const project = await projectRepository.getByUrl(projectUrl);
|
|
106
|
+
|
|
107
|
+
const issue = await issueRepository.get(notifyFinishedIssueUrl, project);
|
|
108
|
+
if (!issue) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
issue.status = 'Preparation';
|
|
112
|
+
await issueRepository.update(issue, project);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('success', async () => {
|
|
116
|
+
if (!token) {
|
|
117
|
+
throw new Error('GH_TOKEN environment variable is required');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const issueRepository = new GitHubIssueRepository(token);
|
|
121
|
+
const projectRepository = new GitHubProjectRepository(token);
|
|
122
|
+
const project = await projectRepository.getByUrl(projectUrl);
|
|
123
|
+
|
|
124
|
+
const beforeIssue = await issueRepository.get(
|
|
125
|
+
notifyFinishedIssueUrl,
|
|
126
|
+
project,
|
|
127
|
+
);
|
|
128
|
+
expect(beforeIssue?.status).toBe('Preparation');
|
|
129
|
+
|
|
130
|
+
const result = execSync(
|
|
131
|
+
'npx ts-node ./src/adapter/entry-points/cli/index.ts notifyFinishedIssuePreparation --projectUrl https://github.com/users/HiromiShikata/projects/49 --issueUrl https://github.com/HiromiShikata/test-repository/issues/1557 --preparationStatus "Preparation" --awaitingQualityCheckStatus "Awaiting quality check"',
|
|
132
|
+
{ encoding: 'utf-8', timeout: 600000 },
|
|
133
|
+
);
|
|
134
|
+
expect(result).toBeDefined();
|
|
135
|
+
|
|
136
|
+
const afterIssue = await issueRepository.get(
|
|
137
|
+
notifyFinishedIssueUrl,
|
|
138
|
+
project,
|
|
139
|
+
);
|
|
140
|
+
expect(afterIssue?.status).toBe('Awaiting quality check');
|
|
141
|
+
}, 600000);
|
|
142
|
+
});
|
|
143
|
+
});
|