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
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# CONTRIBUTING
|
|
2
|
+
|
|
3
|
+
First off, thank you for considering contributing to our project. We value all our contributors and the insights they bring to the table.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Code of Conduct](#code-of-conduct)
|
|
8
|
+
- [Coding Guidelines](#coding-guidelines)
|
|
9
|
+
- [Clean Architecture Rules](#clean-architecture-rules)
|
|
10
|
+
- [Type-Safe Programming](#type-safe-programming)
|
|
11
|
+
- [Writing Tests](#writing-tests)
|
|
12
|
+
- [How to Submit Changes](#how-to-submit-changes)
|
|
13
|
+
- [Recognition](#recognition)
|
|
14
|
+
- [Getting Help](#getting-help)
|
|
15
|
+
|
|
16
|
+
## Code of Conduct
|
|
17
|
+
|
|
18
|
+
We expect everyone participating in this project to adhere to our Code of Conduct. Below are the main points, but we encourage you to read the full Code of Conduct.
|
|
19
|
+
|
|
20
|
+
- Treat everyone with respect.
|
|
21
|
+
- Avoid making assumptions about other people's identities and experiences.
|
|
22
|
+
- Keep criticism constructive and respectful.
|
|
23
|
+
- Report any incidents of harassment or inappropriate behavior to the project maintainers.
|
|
24
|
+
|
|
25
|
+
## Coding Guidelines
|
|
26
|
+
|
|
27
|
+
### Clean Architecture Rules
|
|
28
|
+
|
|
29
|
+
Our project follows the principles of Clean Architecture. This means that we separate concerns, make the project independent of any frameworks, and make it testable and independent of the UI.
|
|
30
|
+
|
|
31
|
+
In addition, our domain layer should not depend on the adapter layer. Please ensure that any contributions you make maintain this separation and adhere to these principles.
|
|
32
|
+
|
|
33
|
+
### Type-Safe Programming
|
|
34
|
+
|
|
35
|
+
We aim for a type-safe programming style, so please avoid using `any` or `as`. Instead, use type guards or other means to determine types.
|
|
36
|
+
|
|
37
|
+
### Code Style
|
|
38
|
+
|
|
39
|
+
- As a general rule, please refrain from writing comments whenever possible.
|
|
40
|
+
- Your first approach should be to make your variable and function names as descriptive and self-explanatory as possible.
|
|
41
|
+
- Only when this is not sufficient, and the functionality or purpose of the code is not immediately clear, should comments be used.
|
|
42
|
+
- We encourage the use of the arrow function style as much as possible. It offers a more concise syntax and aligns with contemporary JavaScript practices. Please favor this style when contributing to our codebase.
|
|
43
|
+
|
|
44
|
+
## Writing Tests
|
|
45
|
+
|
|
46
|
+
Testing is a crucial part of our development process. We expect all code contributions to be accompanied by corresponding tests. This helps us maintain the quality of the project and catch any potential issues early.
|
|
47
|
+
|
|
48
|
+
### Unit Test Template
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
import { ReplaceAllWords } from './ReplaceAllWords';
|
|
52
|
+
import { FileRepository } from './adapter-interfaces/FileRepository';
|
|
53
|
+
import { StringConvertor } from './adapter-interfaces/StringConvertor';
|
|
54
|
+
type Mocked<T> = jest.Mocked<T> & jest.MockedObject<T>
|
|
55
|
+
|
|
56
|
+
describe('ReplaceAllWords', () => {
|
|
57
|
+
|
|
58
|
+
beforeEach(() => {
|
|
59
|
+
jest.resetAllMocks();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const createUseCaseAndMockRepositories = ()=>{
|
|
63
|
+
const fileRepository: Mocked<FileRepository> = {
|
|
64
|
+
readdirSync: jest.fn(),
|
|
65
|
+
renameSync: jest.fn(),
|
|
66
|
+
lstatSync: jest.fn(),
|
|
67
|
+
statSync: jest.fn(),
|
|
68
|
+
readFileSync: jest.fn(),
|
|
69
|
+
writeFileSync: jest.fn(),
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const stringConvertor: Mocked<StringConvertor> = {
|
|
73
|
+
camelCase: jest.fn(),
|
|
74
|
+
snakeCase: jest.fn(),
|
|
75
|
+
pascalCase: jest.fn(),
|
|
76
|
+
kebabCase: jest.fn(),
|
|
77
|
+
screamSnakeCase: jest.fn(),
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const useCase: ReplaceAllWords = new ReplaceAllWords(fileRepository, stringConvertor);
|
|
81
|
+
return {
|
|
82
|
+
fileRepository,
|
|
83
|
+
stringConvertor,
|
|
84
|
+
useCase
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## How to Submit Changes
|
|
92
|
+
|
|
93
|
+
Once you've identified a bug or an enhancement you'd like to work on, follow these steps to make and submit your changes:
|
|
94
|
+
|
|
95
|
+
1. Fork the repository.
|
|
96
|
+
2. Create a new branch.
|
|
97
|
+
3. Make your changes, ensuring you follow our coding conventions and style guide.
|
|
98
|
+
4. Write tests for your changes.
|
|
99
|
+
5. Submit a pull request.
|
|
100
|
+
|
|
101
|
+
Please note that we may take a while to respond, but we appreciate your patience. We aim to make the contribution process as transparent as possible and will keep you updated every step of the way.
|
|
102
|
+
|
|
103
|
+
## Getting Help
|
|
104
|
+
|
|
105
|
+
If you need help or have any questions, please create an issue in the project's GitHub repository. We aim to respond to issues promptly and appreciate your patience.
|
|
106
|
+
|
|
107
|
+
Again, thank you for considering contributing to our project. Your input is valuable, and we look forward to working with you.
|
package/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# npm-cli-gh-issue-preparator
|
|
2
|
+
|
|
3
|
+
[](https://github.com/HiromiShikata/npm-cli-gh-issue-preparator/actions/workflows/test.yml)
|
|
4
|
+
[](https://github.com/prettier/prettier)
|
|
5
|
+
[](https://github.com/semantic-release/semantic-release)
|
|
6
|
+
|
|
7
|
+
Welcome to npm-cli-gh-issue-preparator, this tool helps you to prepare you task by AI.
|
|
8
|
+
|
|
9
|
+
## Usage 🛠️
|
|
10
|
+
|
|
11
|
+
Here's how you can use npm-cli-gh-issue-preparator:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
Usage: npm-cli-gh-issue-preparator [options] [command]
|
|
15
|
+
|
|
16
|
+
CLI tool to prepare GitHub issues
|
|
17
|
+
|
|
18
|
+
Options:
|
|
19
|
+
-h, --help display help for command
|
|
20
|
+
|
|
21
|
+
Commands:
|
|
22
|
+
startDaemon [options] Start daemon to prepare GitHub issues
|
|
23
|
+
notifyFinishedIssuePreparation [options] Notify that issue preparation is finished
|
|
24
|
+
help [command] display help for command
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Example 📖
|
|
28
|
+
|
|
29
|
+
Here's a quick example to illustrate its usage:
|
|
30
|
+
|
|
31
|
+
### Start daemon
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
npx npm-cli-gh-issue-preparator startDaemon --projectUrl <projectUrl> --awaitingWorkspaceStatus "Awaiting workspace" --preparationStatus "Preparation" --defaultAgentName "impl"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Notify finished issue preparation
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
npx npm-cli-gh-issue-preparator notifyFinishedIssuePreparation --projectUrl <projectUrl> --issueUrl <issueUrl> --preparationStatus "Preparation" --awaitingQualityCheckStatus "Awaiting quality check"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Contributing
|
|
44
|
+
|
|
45
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md)
|
|
46
|
+
|
|
47
|
+
## License
|
|
48
|
+
|
|
49
|
+
MIT
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.program = void 0;
|
|
8
|
+
const dotenv_1 = __importDefault(require("dotenv"));
|
|
9
|
+
dotenv_1.default.config();
|
|
10
|
+
const commander_1 = require("commander");
|
|
11
|
+
const StartPreparationUseCase_1 = require("../../../domain/usecases/StartPreparationUseCase");
|
|
12
|
+
const NotifyFinishedIssuePreparationUseCase_1 = require("../../../domain/usecases/NotifyFinishedIssuePreparationUseCase");
|
|
13
|
+
const GitHubProjectRepository_1 = require("../../repositories/GitHubProjectRepository");
|
|
14
|
+
const GitHubIssueRepository_1 = require("../../repositories/GitHubIssueRepository");
|
|
15
|
+
const NodeLocalCommandRunner_1 = require("../../repositories/NodeLocalCommandRunner");
|
|
16
|
+
const program = new commander_1.Command();
|
|
17
|
+
exports.program = program;
|
|
18
|
+
program
|
|
19
|
+
.name('npm-cli-gh-issue-preparator')
|
|
20
|
+
.description('CLI tool to prepare GitHub issues');
|
|
21
|
+
program
|
|
22
|
+
.command('startDaemon')
|
|
23
|
+
.description('Start daemon to prepare GitHub issues')
|
|
24
|
+
.requiredOption('--projectUrl <url>', 'GitHub project URL')
|
|
25
|
+
.requiredOption('--awaitingWorkspaceStatus <status>', 'Status for issues awaiting workspace')
|
|
26
|
+
.requiredOption('--preparationStatus <status>', 'Status for issues in preparation')
|
|
27
|
+
.requiredOption('--defaultAgentName <name>', 'Default agent name')
|
|
28
|
+
.action(async (options) => {
|
|
29
|
+
const token = process.env.GH_TOKEN;
|
|
30
|
+
if (!token) {
|
|
31
|
+
console.error('GH_TOKEN environment variable is required');
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
const projectRepository = new GitHubProjectRepository_1.GitHubProjectRepository(token);
|
|
35
|
+
const issueRepository = new GitHubIssueRepository_1.GitHubIssueRepository(token);
|
|
36
|
+
const localCommandRunner = new NodeLocalCommandRunner_1.NodeLocalCommandRunner();
|
|
37
|
+
const useCase = new StartPreparationUseCase_1.StartPreparationUseCase(projectRepository, issueRepository, localCommandRunner);
|
|
38
|
+
await useCase.run({
|
|
39
|
+
projectUrl: options.projectUrl,
|
|
40
|
+
awaitingWorkspaceStatus: options.awaitingWorkspaceStatus,
|
|
41
|
+
preparationStatus: options.preparationStatus,
|
|
42
|
+
defaultAgentName: options.defaultAgentName,
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
program
|
|
46
|
+
.command('notifyFinishedIssuePreparation')
|
|
47
|
+
.description('Notify that issue preparation is finished')
|
|
48
|
+
.requiredOption('--projectUrl <url>', 'GitHub project URL')
|
|
49
|
+
.requiredOption('--issueUrl <url>', 'GitHub issue URL')
|
|
50
|
+
.requiredOption('--preparationStatus <status>', 'Status for issues in preparation')
|
|
51
|
+
.requiredOption('--awaitingQualityCheckStatus <status>', 'Status for issues awaiting quality check')
|
|
52
|
+
.action(async (options) => {
|
|
53
|
+
const token = process.env.GH_TOKEN;
|
|
54
|
+
if (!token) {
|
|
55
|
+
console.error('GH_TOKEN environment variable is required');
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
const projectRepository = new GitHubProjectRepository_1.GitHubProjectRepository(token);
|
|
59
|
+
const issueRepository = new GitHubIssueRepository_1.GitHubIssueRepository(token);
|
|
60
|
+
const useCase = new NotifyFinishedIssuePreparationUseCase_1.NotifyFinishedIssuePreparationUseCase(projectRepository, issueRepository);
|
|
61
|
+
await useCase.run({
|
|
62
|
+
projectUrl: options.projectUrl,
|
|
63
|
+
issueUrl: options.issueUrl,
|
|
64
|
+
preparationStatus: options.preparationStatus,
|
|
65
|
+
awaitingQualityCheckStatus: options.awaitingQualityCheckStatus,
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
/* istanbul ignore next */
|
|
69
|
+
if (process.argv && require.main === module) {
|
|
70
|
+
program.parse(process.argv);
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/adapter/entry-points/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GitHubIssueRepository = void 0;
|
|
4
|
+
function isProjectItemsResponse(value) {
|
|
5
|
+
if (typeof value !== 'object' || value === null)
|
|
6
|
+
return false;
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
function isUpdateItemResponse(value) {
|
|
10
|
+
if (typeof value !== 'object' || value === null)
|
|
11
|
+
return false;
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
function isStatusFieldsResponse(value) {
|
|
15
|
+
if (typeof value !== 'object' || value === null)
|
|
16
|
+
return false;
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
class GitHubIssueRepository {
|
|
20
|
+
constructor(token) {
|
|
21
|
+
this.token = token;
|
|
22
|
+
}
|
|
23
|
+
parseProjectInfo(project) {
|
|
24
|
+
const urlMatch = project.url.match(/github\.com\/(?:orgs|users)\/([^/]+)\/projects\/(\d+)/);
|
|
25
|
+
if (!urlMatch) {
|
|
26
|
+
throw new Error(`Invalid GitHub project URL: ${project.url}`);
|
|
27
|
+
}
|
|
28
|
+
const owner = urlMatch[1];
|
|
29
|
+
const projectNumber = parseInt(urlMatch[2], 10);
|
|
30
|
+
return { owner, projectNumber };
|
|
31
|
+
}
|
|
32
|
+
buildProjectItemsQuery() {
|
|
33
|
+
return `
|
|
34
|
+
query($owner: String!, $number: Int!) {
|
|
35
|
+
organization(login: $owner) {
|
|
36
|
+
projectV2(number: $number) {
|
|
37
|
+
items(first: 100) {
|
|
38
|
+
nodes {
|
|
39
|
+
id
|
|
40
|
+
content {
|
|
41
|
+
... on Issue {
|
|
42
|
+
url
|
|
43
|
+
title
|
|
44
|
+
number
|
|
45
|
+
labels(first: 10) {
|
|
46
|
+
nodes {
|
|
47
|
+
name
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
fieldValues(first: 20) {
|
|
53
|
+
nodes {
|
|
54
|
+
__typename
|
|
55
|
+
... on ProjectV2ItemFieldSingleSelectValue {
|
|
56
|
+
name
|
|
57
|
+
field {
|
|
58
|
+
... on ProjectV2SingleSelectField {
|
|
59
|
+
name
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
... on ProjectV2ItemFieldTextValue {
|
|
64
|
+
text
|
|
65
|
+
field {
|
|
66
|
+
... on ProjectV2Field {
|
|
67
|
+
name
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
user(login: $owner) {
|
|
78
|
+
projectV2(number: $number) {
|
|
79
|
+
items(first: 100) {
|
|
80
|
+
nodes {
|
|
81
|
+
id
|
|
82
|
+
content {
|
|
83
|
+
... on Issue {
|
|
84
|
+
url
|
|
85
|
+
title
|
|
86
|
+
number
|
|
87
|
+
labels(first: 10) {
|
|
88
|
+
nodes {
|
|
89
|
+
name
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
fieldValues(first: 20) {
|
|
95
|
+
nodes {
|
|
96
|
+
__typename
|
|
97
|
+
... on ProjectV2ItemFieldSingleSelectValue {
|
|
98
|
+
name
|
|
99
|
+
field {
|
|
100
|
+
... on ProjectV2SingleSelectField {
|
|
101
|
+
name
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
... on ProjectV2ItemFieldTextValue {
|
|
106
|
+
text
|
|
107
|
+
field {
|
|
108
|
+
... on ProjectV2Field {
|
|
109
|
+
name
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
`;
|
|
121
|
+
}
|
|
122
|
+
async getStatusOptionId(project, statusName) {
|
|
123
|
+
const { owner, projectNumber } = this.parseProjectInfo(project);
|
|
124
|
+
const query = `
|
|
125
|
+
query($owner: String!, $number: Int!) {
|
|
126
|
+
organization(login: $owner) {
|
|
127
|
+
projectV2(number: $number) {
|
|
128
|
+
fields(first: 10) {
|
|
129
|
+
nodes {
|
|
130
|
+
... on ProjectV2SingleSelectField {
|
|
131
|
+
id
|
|
132
|
+
name
|
|
133
|
+
options {
|
|
134
|
+
id
|
|
135
|
+
name
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
user(login: $owner) {
|
|
143
|
+
projectV2(number: $number) {
|
|
144
|
+
fields(first: 10) {
|
|
145
|
+
nodes {
|
|
146
|
+
... on ProjectV2SingleSelectField {
|
|
147
|
+
id
|
|
148
|
+
name
|
|
149
|
+
options {
|
|
150
|
+
id
|
|
151
|
+
name
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
`;
|
|
160
|
+
const response = await fetch('https://api.github.com/graphql', {
|
|
161
|
+
method: 'POST',
|
|
162
|
+
headers: {
|
|
163
|
+
Authorization: `Bearer ${this.token}`,
|
|
164
|
+
'Content-Type': 'application/json',
|
|
165
|
+
},
|
|
166
|
+
body: JSON.stringify({
|
|
167
|
+
query,
|
|
168
|
+
variables: {
|
|
169
|
+
owner,
|
|
170
|
+
number: projectNumber,
|
|
171
|
+
},
|
|
172
|
+
}),
|
|
173
|
+
});
|
|
174
|
+
if (!response.ok) {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
const responseData = await response.json();
|
|
178
|
+
if (!isStatusFieldsResponse(responseData)) {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
const result = responseData;
|
|
182
|
+
const fields = result.data?.organization?.projectV2?.fields.nodes ||
|
|
183
|
+
result.data?.user?.projectV2?.fields.nodes ||
|
|
184
|
+
[];
|
|
185
|
+
const statusField = fields.find((f) => f.name === 'Status');
|
|
186
|
+
if (!statusField) {
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
const option = statusField.options.find((o) => o.name === statusName);
|
|
190
|
+
if (!option) {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
fieldId: statusField.id,
|
|
195
|
+
optionId: option.id,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
async getAllOpened(project) {
|
|
199
|
+
const { owner, projectNumber } = this.parseProjectInfo(project);
|
|
200
|
+
const query = this.buildProjectItemsQuery();
|
|
201
|
+
const response = await fetch('https://api.github.com/graphql', {
|
|
202
|
+
method: 'POST',
|
|
203
|
+
headers: {
|
|
204
|
+
Authorization: `Bearer ${this.token}`,
|
|
205
|
+
'Content-Type': 'application/json',
|
|
206
|
+
},
|
|
207
|
+
body: JSON.stringify({
|
|
208
|
+
query,
|
|
209
|
+
variables: {
|
|
210
|
+
owner,
|
|
211
|
+
number: projectNumber,
|
|
212
|
+
},
|
|
213
|
+
}),
|
|
214
|
+
});
|
|
215
|
+
if (!response.ok) {
|
|
216
|
+
const errorText = await response.text();
|
|
217
|
+
throw new Error(`GitHub API error: ${errorText}`);
|
|
218
|
+
}
|
|
219
|
+
const responseData = await response.json();
|
|
220
|
+
if (!isProjectItemsResponse(responseData)) {
|
|
221
|
+
throw new Error('Invalid API response format');
|
|
222
|
+
}
|
|
223
|
+
const result = responseData;
|
|
224
|
+
const items = result.data?.organization?.projectV2?.items.nodes ||
|
|
225
|
+
result.data?.user?.projectV2?.items.nodes ||
|
|
226
|
+
[];
|
|
227
|
+
const issues = [];
|
|
228
|
+
for (const item of items) {
|
|
229
|
+
if (!item.content)
|
|
230
|
+
continue;
|
|
231
|
+
const statusField = item.fieldValues?.nodes.find((fv) => fv.field?.name === 'Status');
|
|
232
|
+
const status = statusField?.name || '';
|
|
233
|
+
issues.push({
|
|
234
|
+
id: item.id,
|
|
235
|
+
url: item.content.url,
|
|
236
|
+
title: item.content.title,
|
|
237
|
+
labels: item.content.labels.nodes.map((l) => l.name),
|
|
238
|
+
status,
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
return issues;
|
|
242
|
+
}
|
|
243
|
+
async update(issue, project) {
|
|
244
|
+
const statusInfo = await this.getStatusOptionId(project, issue.status);
|
|
245
|
+
if (!statusInfo) {
|
|
246
|
+
throw new Error(`Status option not found for status: ${issue.status}`);
|
|
247
|
+
}
|
|
248
|
+
const mutation = `
|
|
249
|
+
mutation($projectId: ID!, $itemId: ID!, $fieldId: ID!, $value: ProjectV2FieldValue!) {
|
|
250
|
+
updateProjectV2ItemFieldValue(
|
|
251
|
+
input: {
|
|
252
|
+
projectId: $projectId
|
|
253
|
+
itemId: $itemId
|
|
254
|
+
fieldId: $fieldId
|
|
255
|
+
value: $value
|
|
256
|
+
}
|
|
257
|
+
) {
|
|
258
|
+
projectV2Item {
|
|
259
|
+
id
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
`;
|
|
264
|
+
const response = await fetch('https://api.github.com/graphql', {
|
|
265
|
+
method: 'POST',
|
|
266
|
+
headers: {
|
|
267
|
+
Authorization: `Bearer ${this.token}`,
|
|
268
|
+
'Content-Type': 'application/json',
|
|
269
|
+
},
|
|
270
|
+
body: JSON.stringify({
|
|
271
|
+
query: mutation,
|
|
272
|
+
variables: {
|
|
273
|
+
projectId: project.id,
|
|
274
|
+
itemId: issue.id,
|
|
275
|
+
fieldId: statusInfo.fieldId,
|
|
276
|
+
value: { singleSelectOptionId: statusInfo.optionId },
|
|
277
|
+
},
|
|
278
|
+
}),
|
|
279
|
+
});
|
|
280
|
+
const responseData = await response.json();
|
|
281
|
+
if (!response.ok) {
|
|
282
|
+
throw new Error(`GitHub API error: ${JSON.stringify(responseData)}`);
|
|
283
|
+
}
|
|
284
|
+
if (typeof responseData === 'object' &&
|
|
285
|
+
responseData !== null &&
|
|
286
|
+
'errors' in responseData) {
|
|
287
|
+
throw new Error(`GraphQL errors: ${JSON.stringify(responseData.errors)}`);
|
|
288
|
+
}
|
|
289
|
+
if (!isUpdateItemResponse(responseData)) {
|
|
290
|
+
throw new Error('Invalid API response format');
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
async get(issueUrl, project) {
|
|
294
|
+
const { owner, projectNumber } = this.parseProjectInfo(project);
|
|
295
|
+
const query = this.buildProjectItemsQuery();
|
|
296
|
+
const response = await fetch('https://api.github.com/graphql', {
|
|
297
|
+
method: 'POST',
|
|
298
|
+
headers: {
|
|
299
|
+
Authorization: `Bearer ${this.token}`,
|
|
300
|
+
'Content-Type': 'application/json',
|
|
301
|
+
},
|
|
302
|
+
body: JSON.stringify({
|
|
303
|
+
query,
|
|
304
|
+
variables: {
|
|
305
|
+
owner,
|
|
306
|
+
number: projectNumber,
|
|
307
|
+
},
|
|
308
|
+
}),
|
|
309
|
+
});
|
|
310
|
+
if (!response.ok) {
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
313
|
+
const responseData = await response.json();
|
|
314
|
+
if (!isProjectItemsResponse(responseData)) {
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
const result = responseData;
|
|
318
|
+
const items = result.data?.organization?.projectV2?.items.nodes ||
|
|
319
|
+
result.data?.user?.projectV2?.items.nodes ||
|
|
320
|
+
[];
|
|
321
|
+
for (const item of items) {
|
|
322
|
+
if (!item.content)
|
|
323
|
+
continue;
|
|
324
|
+
if (item.content.url === issueUrl) {
|
|
325
|
+
const statusField = item.fieldValues?.nodes.find((fv) => fv.field?.name === 'Status');
|
|
326
|
+
const status = statusField?.name || '';
|
|
327
|
+
return {
|
|
328
|
+
id: item.id,
|
|
329
|
+
url: item.content.url,
|
|
330
|
+
title: item.content.title,
|
|
331
|
+
labels: item.content.labels.nodes.map((l) => l.name),
|
|
332
|
+
status,
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
exports.GitHubIssueRepository = GitHubIssueRepository;
|
|
340
|
+
//# sourceMappingURL=GitHubIssueRepository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GitHubIssueRepository.js","sourceRoot":"","sources":["../../../src/adapter/repositories/GitHubIssueRepository.ts"],"names":[],"mappings":"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"}
|