github-issue-tower-defence-management 1.71.0 → 1.72.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/.github/workflows/umino-project.yml +15 -7
- package/CHANGELOG.md +14 -0
- package/README.md +1 -0
- package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js +51 -0
- package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js.map +1 -1
- package/bin/adapter/repositories/issue/GraphqlProjectItemRepository.js +88 -13
- package/bin/adapter/repositories/issue/GraphqlProjectItemRepository.js.map +1 -1
- package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js +37 -1
- package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js.map +1 -1
- package/package.json +1 -1
- package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.test.ts +139 -0
- package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.ts +69 -0
- package/src/adapter/repositories/issue/GraphqlProjectItemRepository.test.ts +184 -0
- package/src/adapter/repositories/issue/GraphqlProjectItemRepository.ts +118 -55
- package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.test.ts +318 -0
- package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.ts +52 -1
- package/src/domain/usecases/adapter-interfaces/IssueRepository.ts +2 -0
- package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts +2 -0
- package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts.map +1 -1
- package/types/adapter/repositories/issue/GraphqlProjectItemRepository.d.ts.map +1 -1
- package/types/domain/usecases/NotifyFinishedIssuePreparationUseCase.d.ts +4 -1
- package/types/domain/usecases/NotifyFinishedIssuePreparationUseCase.d.ts.map +1 -1
- package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts +2 -0
- package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts.map +1 -1
|
@@ -94,6 +94,8 @@ describe('NotifyFinishedIssuePreparationUseCase', () => {
|
|
|
94
94
|
findRelatedOpenPRs: jest.Mock;
|
|
95
95
|
getStoryObjectMap: jest.Mock;
|
|
96
96
|
getOpenPullRequest: jest.Mock;
|
|
97
|
+
getPullRequestChangedFilePaths: jest.Mock;
|
|
98
|
+
approvePullRequest: jest.Mock;
|
|
97
99
|
setDependedIssueUrl: jest.Mock;
|
|
98
100
|
};
|
|
99
101
|
let mockIssueCommentRepository: {
|
|
@@ -126,6 +128,8 @@ describe('NotifyFinishedIssuePreparationUseCase', () => {
|
|
|
126
128
|
updateStatus: jest.fn(),
|
|
127
129
|
findRelatedOpenPRs: jest.fn(),
|
|
128
130
|
getOpenPullRequest: jest.fn(),
|
|
131
|
+
getPullRequestChangedFilePaths: jest.fn().mockResolvedValue([]),
|
|
132
|
+
approvePullRequest: jest.fn().mockResolvedValue(undefined),
|
|
129
133
|
setDependedIssueUrl: jest.fn(),
|
|
130
134
|
};
|
|
131
135
|
|
|
@@ -257,6 +261,75 @@ describe('NotifyFinishedIssuePreparationUseCase', () => {
|
|
|
257
261
|
);
|
|
258
262
|
});
|
|
259
263
|
|
|
264
|
+
it('should throw IssueNotFoundError when a pull request URL has no backing project item (no silent skip)', async () => {
|
|
265
|
+
mockProjectRepository.getByUrl.mockResolvedValue(mockProject);
|
|
266
|
+
mockIssueRepository.get.mockResolvedValue(null);
|
|
267
|
+
|
|
268
|
+
await expect(
|
|
269
|
+
useCase.run({
|
|
270
|
+
projectUrl: 'https://github.com/users/user/projects/1',
|
|
271
|
+
issueUrl: 'https://github.com/user/repo/pull/999',
|
|
272
|
+
thresholdForAutoReject: 3,
|
|
273
|
+
workflowBlockerResolvedWebhookUrl: null,
|
|
274
|
+
allowedIssueAuthors: null,
|
|
275
|
+
}),
|
|
276
|
+
).rejects.toThrow('Issue not found: https://github.com/user/repo/pull/999');
|
|
277
|
+
expect(mockIssueRepository.update).not.toHaveBeenCalled();
|
|
278
|
+
expect(mockIssueRepository.updateStatus).not.toHaveBeenCalled();
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it('should process a pull request URL the same as an issue URL when the project item resolves', async () => {
|
|
282
|
+
const prIssue = createMockIssue({
|
|
283
|
+
url: 'https://github.com/user/repo/pull/77',
|
|
284
|
+
number: 77,
|
|
285
|
+
status: 'Preparation',
|
|
286
|
+
isPr: true,
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
mockProjectRepository.getByUrl.mockResolvedValue(mockProject);
|
|
290
|
+
mockIssueRepository.get.mockResolvedValue(prIssue);
|
|
291
|
+
mockIssueCommentRepository.getCommentsFromIssue.mockResolvedValue([
|
|
292
|
+
createMockComment({ content: 'From: :robot: Agent report' }),
|
|
293
|
+
]);
|
|
294
|
+
mockIssueRepository.getOpenPullRequest.mockResolvedValue({
|
|
295
|
+
url: 'https://github.com/user/repo/pull/77',
|
|
296
|
+
isConflicted: false,
|
|
297
|
+
isPassedAllCiJob: true,
|
|
298
|
+
isCiStateSuccess: true,
|
|
299
|
+
isResolvedAllReviewComments: true,
|
|
300
|
+
isBranchOutOfDate: false,
|
|
301
|
+
missingRequiredCheckNames: [],
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
await useCase.run({
|
|
305
|
+
projectUrl: 'https://github.com/users/user/projects/1',
|
|
306
|
+
issueUrl: 'https://github.com/user/repo/pull/77',
|
|
307
|
+
thresholdForAutoReject: 3,
|
|
308
|
+
workflowBlockerResolvedWebhookUrl: null,
|
|
309
|
+
allowedIssueAuthors: null,
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
expect(mockIssueRepository.get).toHaveBeenCalledWith(
|
|
313
|
+
'https://github.com/user/repo/pull/77',
|
|
314
|
+
mockProject,
|
|
315
|
+
);
|
|
316
|
+
expect(mockIssueRepository.update).toHaveBeenCalledWith(
|
|
317
|
+
expect.objectContaining({
|
|
318
|
+
url: 'https://github.com/user/repo/pull/77',
|
|
319
|
+
status: 'Awaiting Quality Check',
|
|
320
|
+
}),
|
|
321
|
+
mockProject,
|
|
322
|
+
);
|
|
323
|
+
expect(mockIssueRepository.updateStatus).toHaveBeenCalledWith(
|
|
324
|
+
mockProject,
|
|
325
|
+
expect.objectContaining({
|
|
326
|
+
url: 'https://github.com/user/repo/pull/77',
|
|
327
|
+
status: 'Awaiting Quality Check',
|
|
328
|
+
}),
|
|
329
|
+
'awaiting-quality-check-id',
|
|
330
|
+
);
|
|
331
|
+
});
|
|
332
|
+
|
|
260
333
|
it('should throw IllegalIssueStatusError when issue status is not Preparation', async () => {
|
|
261
334
|
const issue = createMockIssue({
|
|
262
335
|
url: 'https://github.com/user/repo/issues/1',
|
|
@@ -2694,4 +2767,249 @@ describe('NotifyFinishedIssuePreparationUseCase', () => {
|
|
|
2694
2767
|
);
|
|
2695
2768
|
});
|
|
2696
2769
|
});
|
|
2770
|
+
|
|
2771
|
+
describe('change-target label auto-approve', () => {
|
|
2772
|
+
const setupApprovedPrScenario = (issueOverrides: Partial<Issue> = {}) => {
|
|
2773
|
+
const issue = createMockIssue({
|
|
2774
|
+
url: 'https://github.com/user/repo/issues/1',
|
|
2775
|
+
status: 'Preparation',
|
|
2776
|
+
...issueOverrides,
|
|
2777
|
+
});
|
|
2778
|
+
mockProjectRepository.getByUrl.mockResolvedValue(mockProject);
|
|
2779
|
+
mockIssueRepository.get.mockResolvedValue(issue);
|
|
2780
|
+
mockIssueCommentRepository.getCommentsFromIssue.mockResolvedValue([
|
|
2781
|
+
createMockComment({ content: 'From: :robot: Agent report' }),
|
|
2782
|
+
]);
|
|
2783
|
+
mockIssueRepository.findRelatedOpenPRs.mockResolvedValue([
|
|
2784
|
+
{
|
|
2785
|
+
url: 'https://github.com/user/repo/pull/1',
|
|
2786
|
+
isConflicted: false,
|
|
2787
|
+
isPassedAllCiJob: true,
|
|
2788
|
+
isCiStateSuccess: true,
|
|
2789
|
+
isResolvedAllReviewComments: true,
|
|
2790
|
+
isBranchOutOfDate: false,
|
|
2791
|
+
missingRequiredCheckNames: [],
|
|
2792
|
+
},
|
|
2793
|
+
]);
|
|
2794
|
+
};
|
|
2795
|
+
|
|
2796
|
+
it('should not approve PR when issue has no change-target label', async () => {
|
|
2797
|
+
setupApprovedPrScenario();
|
|
2798
|
+
|
|
2799
|
+
await useCase.run({
|
|
2800
|
+
projectUrl: 'https://github.com/users/user/projects/1',
|
|
2801
|
+
issueUrl: 'https://github.com/user/repo/issues/1',
|
|
2802
|
+
thresholdForAutoReject: 3,
|
|
2803
|
+
workflowBlockerResolvedWebhookUrl: null,
|
|
2804
|
+
allowedIssueAuthors: null,
|
|
2805
|
+
});
|
|
2806
|
+
|
|
2807
|
+
expect(
|
|
2808
|
+
mockIssueRepository.getPullRequestChangedFilePaths,
|
|
2809
|
+
).not.toHaveBeenCalled();
|
|
2810
|
+
expect(mockIssueRepository.approvePullRequest).not.toHaveBeenCalled();
|
|
2811
|
+
expect(mockIssueRepository.update).toHaveBeenCalledWith(
|
|
2812
|
+
expect.objectContaining({ status: 'Awaiting Quality Check' }),
|
|
2813
|
+
mockProject,
|
|
2814
|
+
);
|
|
2815
|
+
});
|
|
2816
|
+
|
|
2817
|
+
it('should approve PR when issue has change-target label and all files are confined', async () => {
|
|
2818
|
+
setupApprovedPrScenario({ labels: ['change-target:src/domain'] });
|
|
2819
|
+
mockIssueRepository.getPullRequestChangedFilePaths.mockResolvedValue([
|
|
2820
|
+
'src/domain/entities/Foo.ts',
|
|
2821
|
+
'src/domain/usecases/Bar.ts',
|
|
2822
|
+
]);
|
|
2823
|
+
|
|
2824
|
+
await useCase.run({
|
|
2825
|
+
projectUrl: 'https://github.com/users/user/projects/1',
|
|
2826
|
+
issueUrl: 'https://github.com/user/repo/issues/1',
|
|
2827
|
+
thresholdForAutoReject: 3,
|
|
2828
|
+
workflowBlockerResolvedWebhookUrl: null,
|
|
2829
|
+
allowedIssueAuthors: null,
|
|
2830
|
+
});
|
|
2831
|
+
|
|
2832
|
+
expect(
|
|
2833
|
+
mockIssueRepository.getPullRequestChangedFilePaths,
|
|
2834
|
+
).toHaveBeenCalledWith('https://github.com/user/repo/pull/1');
|
|
2835
|
+
expect(mockIssueRepository.approvePullRequest).toHaveBeenCalledWith(
|
|
2836
|
+
'https://github.com/user/repo/pull/1',
|
|
2837
|
+
);
|
|
2838
|
+
expect(mockIssueRepository.update).toHaveBeenCalledWith(
|
|
2839
|
+
expect.objectContaining({ status: 'Awaiting Quality Check' }),
|
|
2840
|
+
mockProject,
|
|
2841
|
+
);
|
|
2842
|
+
});
|
|
2843
|
+
|
|
2844
|
+
it('should not approve PR when any changed file is outside the labeled path', async () => {
|
|
2845
|
+
setupApprovedPrScenario({ labels: ['change-target:src/domain'] });
|
|
2846
|
+
mockIssueRepository.getPullRequestChangedFilePaths.mockResolvedValue([
|
|
2847
|
+
'src/domain/entities/Foo.ts',
|
|
2848
|
+
'src/adapter/repositories/Outside.ts',
|
|
2849
|
+
]);
|
|
2850
|
+
|
|
2851
|
+
await useCase.run({
|
|
2852
|
+
projectUrl: 'https://github.com/users/user/projects/1',
|
|
2853
|
+
issueUrl: 'https://github.com/user/repo/issues/1',
|
|
2854
|
+
thresholdForAutoReject: 3,
|
|
2855
|
+
workflowBlockerResolvedWebhookUrl: null,
|
|
2856
|
+
allowedIssueAuthors: null,
|
|
2857
|
+
});
|
|
2858
|
+
|
|
2859
|
+
expect(
|
|
2860
|
+
mockIssueRepository.getPullRequestChangedFilePaths,
|
|
2861
|
+
).toHaveBeenCalledWith('https://github.com/user/repo/pull/1');
|
|
2862
|
+
expect(mockIssueRepository.approvePullRequest).not.toHaveBeenCalled();
|
|
2863
|
+
expect(mockIssueRepository.update).toHaveBeenCalledWith(
|
|
2864
|
+
expect.objectContaining({ status: 'Awaiting Quality Check' }),
|
|
2865
|
+
mockProject,
|
|
2866
|
+
);
|
|
2867
|
+
});
|
|
2868
|
+
|
|
2869
|
+
it('should approve when files are confined under any of multiple change-target labels', async () => {
|
|
2870
|
+
setupApprovedPrScenario({
|
|
2871
|
+
labels: ['change-target:src/domain', 'change-target:docs'],
|
|
2872
|
+
});
|
|
2873
|
+
mockIssueRepository.getPullRequestChangedFilePaths.mockResolvedValue([
|
|
2874
|
+
'src/domain/entities/Foo.ts',
|
|
2875
|
+
'docs/intro.md',
|
|
2876
|
+
]);
|
|
2877
|
+
|
|
2878
|
+
await useCase.run({
|
|
2879
|
+
projectUrl: 'https://github.com/users/user/projects/1',
|
|
2880
|
+
issueUrl: 'https://github.com/user/repo/issues/1',
|
|
2881
|
+
thresholdForAutoReject: 3,
|
|
2882
|
+
workflowBlockerResolvedWebhookUrl: null,
|
|
2883
|
+
allowedIssueAuthors: null,
|
|
2884
|
+
});
|
|
2885
|
+
|
|
2886
|
+
expect(mockIssueRepository.approvePullRequest).toHaveBeenCalledWith(
|
|
2887
|
+
'https://github.com/user/repo/pull/1',
|
|
2888
|
+
);
|
|
2889
|
+
});
|
|
2890
|
+
|
|
2891
|
+
it('should not approve when PR has more than 100 changed files and one file beyond entry 100 is outside the labeled path', async () => {
|
|
2892
|
+
setupApprovedPrScenario({ labels: ['change-target:src/domain'] });
|
|
2893
|
+
const filePaths: string[] = [];
|
|
2894
|
+
for (let i = 0; i < 150; i += 1) {
|
|
2895
|
+
filePaths.push(`src/domain/file${i}.ts`);
|
|
2896
|
+
}
|
|
2897
|
+
filePaths.push('src/adapter/Outside.ts');
|
|
2898
|
+
mockIssueRepository.getPullRequestChangedFilePaths.mockResolvedValue(
|
|
2899
|
+
filePaths,
|
|
2900
|
+
);
|
|
2901
|
+
|
|
2902
|
+
await useCase.run({
|
|
2903
|
+
projectUrl: 'https://github.com/users/user/projects/1',
|
|
2904
|
+
issueUrl: 'https://github.com/user/repo/issues/1',
|
|
2905
|
+
thresholdForAutoReject: 3,
|
|
2906
|
+
workflowBlockerResolvedWebhookUrl: null,
|
|
2907
|
+
allowedIssueAuthors: null,
|
|
2908
|
+
});
|
|
2909
|
+
|
|
2910
|
+
expect(mockIssueRepository.approvePullRequest).not.toHaveBeenCalled();
|
|
2911
|
+
});
|
|
2912
|
+
|
|
2913
|
+
it('should match boundary-safely (change-target:foo matches foo/bar.ts but not foobar/baz.ts)', async () => {
|
|
2914
|
+
setupApprovedPrScenario({ labels: ['change-target:foo'] });
|
|
2915
|
+
mockIssueRepository.getPullRequestChangedFilePaths.mockResolvedValue([
|
|
2916
|
+
'foo/bar.ts',
|
|
2917
|
+
'foobar/baz.ts',
|
|
2918
|
+
]);
|
|
2919
|
+
|
|
2920
|
+
await useCase.run({
|
|
2921
|
+
projectUrl: 'https://github.com/users/user/projects/1',
|
|
2922
|
+
issueUrl: 'https://github.com/user/repo/issues/1',
|
|
2923
|
+
thresholdForAutoReject: 3,
|
|
2924
|
+
workflowBlockerResolvedWebhookUrl: null,
|
|
2925
|
+
allowedIssueAuthors: null,
|
|
2926
|
+
});
|
|
2927
|
+
|
|
2928
|
+
expect(mockIssueRepository.approvePullRequest).not.toHaveBeenCalled();
|
|
2929
|
+
});
|
|
2930
|
+
|
|
2931
|
+
it('should approve when changed files match exact path or subpath of the labeled path', async () => {
|
|
2932
|
+
setupApprovedPrScenario({ labels: ['change-target:foo'] });
|
|
2933
|
+
mockIssueRepository.getPullRequestChangedFilePaths.mockResolvedValue([
|
|
2934
|
+
'foo/bar.ts',
|
|
2935
|
+
'foo/nested/baz.ts',
|
|
2936
|
+
]);
|
|
2937
|
+
|
|
2938
|
+
await useCase.run({
|
|
2939
|
+
projectUrl: 'https://github.com/users/user/projects/1',
|
|
2940
|
+
issueUrl: 'https://github.com/user/repo/issues/1',
|
|
2941
|
+
thresholdForAutoReject: 3,
|
|
2942
|
+
workflowBlockerResolvedWebhookUrl: null,
|
|
2943
|
+
allowedIssueAuthors: null,
|
|
2944
|
+
});
|
|
2945
|
+
|
|
2946
|
+
expect(mockIssueRepository.approvePullRequest).toHaveBeenCalledWith(
|
|
2947
|
+
'https://github.com/user/repo/pull/1',
|
|
2948
|
+
);
|
|
2949
|
+
});
|
|
2950
|
+
|
|
2951
|
+
it('should not approve when PR has zero changed files', async () => {
|
|
2952
|
+
setupApprovedPrScenario({ labels: ['change-target:src/domain'] });
|
|
2953
|
+
mockIssueRepository.getPullRequestChangedFilePaths.mockResolvedValue([]);
|
|
2954
|
+
|
|
2955
|
+
await useCase.run({
|
|
2956
|
+
projectUrl: 'https://github.com/users/user/projects/1',
|
|
2957
|
+
issueUrl: 'https://github.com/user/repo/issues/1',
|
|
2958
|
+
thresholdForAutoReject: 3,
|
|
2959
|
+
workflowBlockerResolvedWebhookUrl: null,
|
|
2960
|
+
allowedIssueAuthors: null,
|
|
2961
|
+
});
|
|
2962
|
+
|
|
2963
|
+
expect(
|
|
2964
|
+
mockIssueRepository.getPullRequestChangedFilePaths,
|
|
2965
|
+
).toHaveBeenCalledWith('https://github.com/user/repo/pull/1');
|
|
2966
|
+
expect(mockIssueRepository.approvePullRequest).not.toHaveBeenCalled();
|
|
2967
|
+
});
|
|
2968
|
+
|
|
2969
|
+
it('should not approve when there is no approved PR even if change-target label is present', async () => {
|
|
2970
|
+
const issue = createMockIssue({
|
|
2971
|
+
url: 'https://github.com/user/repo/issues/1',
|
|
2972
|
+
status: 'Preparation',
|
|
2973
|
+
labels: ['change-target:src/domain'],
|
|
2974
|
+
});
|
|
2975
|
+
mockProjectRepository.getByUrl.mockResolvedValue(mockProject);
|
|
2976
|
+
mockIssueRepository.get.mockResolvedValue(issue);
|
|
2977
|
+
mockIssueCommentRepository.getCommentsFromIssue.mockResolvedValue([
|
|
2978
|
+
createMockComment({ content: 'From: :robot: Agent report' }),
|
|
2979
|
+
]);
|
|
2980
|
+
mockIssueRepository.findRelatedOpenPRs.mockResolvedValue([]);
|
|
2981
|
+
|
|
2982
|
+
await useCase.run({
|
|
2983
|
+
projectUrl: 'https://github.com/users/user/projects/1',
|
|
2984
|
+
issueUrl: 'https://github.com/user/repo/issues/1',
|
|
2985
|
+
thresholdForAutoReject: 3,
|
|
2986
|
+
workflowBlockerResolvedWebhookUrl: null,
|
|
2987
|
+
allowedIssueAuthors: null,
|
|
2988
|
+
});
|
|
2989
|
+
|
|
2990
|
+
expect(
|
|
2991
|
+
mockIssueRepository.getPullRequestChangedFilePaths,
|
|
2992
|
+
).not.toHaveBeenCalled();
|
|
2993
|
+
expect(mockIssueRepository.approvePullRequest).not.toHaveBeenCalled();
|
|
2994
|
+
});
|
|
2995
|
+
|
|
2996
|
+
it('should normalize trailing slashes in change-target label paths', async () => {
|
|
2997
|
+
setupApprovedPrScenario({ labels: ['change-target:src/domain/'] });
|
|
2998
|
+
mockIssueRepository.getPullRequestChangedFilePaths.mockResolvedValue([
|
|
2999
|
+
'src/domain/entities/Foo.ts',
|
|
3000
|
+
]);
|
|
3001
|
+
|
|
3002
|
+
await useCase.run({
|
|
3003
|
+
projectUrl: 'https://github.com/users/user/projects/1',
|
|
3004
|
+
issueUrl: 'https://github.com/user/repo/issues/1',
|
|
3005
|
+
thresholdForAutoReject: 3,
|
|
3006
|
+
workflowBlockerResolvedWebhookUrl: null,
|
|
3007
|
+
allowedIssueAuthors: null,
|
|
3008
|
+
});
|
|
3009
|
+
|
|
3010
|
+
expect(mockIssueRepository.approvePullRequest).toHaveBeenCalledWith(
|
|
3011
|
+
'https://github.com/user/repo/pull/1',
|
|
3012
|
+
);
|
|
3013
|
+
});
|
|
3014
|
+
});
|
|
2697
3015
|
});
|
|
@@ -49,6 +49,8 @@ export class NotifyFinishedIssuePreparationUseCase {
|
|
|
49
49
|
| 'findRelatedOpenPRs'
|
|
50
50
|
| 'getStoryObjectMap'
|
|
51
51
|
| 'getOpenPullRequest'
|
|
52
|
+
| 'getPullRequestChangedFilePaths'
|
|
53
|
+
| 'approvePullRequest'
|
|
52
54
|
| 'setDependedIssueUrl'
|
|
53
55
|
>,
|
|
54
56
|
private readonly issueCommentRepository: Pick<
|
|
@@ -171,7 +173,7 @@ export class NotifyFinishedIssuePreparationUseCase {
|
|
|
171
173
|
const isTrustedAuthor = (author: string): boolean =>
|
|
172
174
|
this.isAuthorTrusted(author, params.allowedIssueAuthors ?? null);
|
|
173
175
|
|
|
174
|
-
const { rejections } = await this.collectRejections(
|
|
176
|
+
const { rejections, approvedPrUrl } = await this.collectRejections(
|
|
175
177
|
issue,
|
|
176
178
|
comments,
|
|
177
179
|
isTrustedAuthor,
|
|
@@ -225,6 +227,7 @@ export class NotifyFinishedIssuePreparationUseCase {
|
|
|
225
227
|
}
|
|
226
228
|
|
|
227
229
|
if (rejections.length <= 0) {
|
|
230
|
+
await this.maybeAutoApprovePrByChangeTarget(issue, approvedPrUrl);
|
|
228
231
|
issue.status = AWAITING_QUALITY_CHECK_STATUS_NAME;
|
|
229
232
|
await this.issueRepository.update(issue, project);
|
|
230
233
|
await this.issueRepository.updateStatus(
|
|
@@ -271,6 +274,54 @@ export class NotifyFinishedIssuePreparationUseCase {
|
|
|
271
274
|
): boolean =>
|
|
272
275
|
allowedIssueAuthors === null || allowedIssueAuthors.includes(author);
|
|
273
276
|
|
|
277
|
+
private extractChangeTargetPaths = (labels: string[]): string[] => {
|
|
278
|
+
const prefix = 'change-target:';
|
|
279
|
+
const paths: string[] = [];
|
|
280
|
+
for (const label of labels) {
|
|
281
|
+
if (!label.startsWith(prefix)) continue;
|
|
282
|
+
const raw = label.slice(prefix.length).trim();
|
|
283
|
+
if (raw.length === 0) continue;
|
|
284
|
+
const normalized = raw.replace(/\/+$/, '');
|
|
285
|
+
if (normalized.length === 0) continue;
|
|
286
|
+
paths.push(normalized);
|
|
287
|
+
}
|
|
288
|
+
return paths;
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
private isFilePathConfinedToAllowedPaths = (
|
|
292
|
+
filePath: string,
|
|
293
|
+
allowedPaths: string[],
|
|
294
|
+
): boolean =>
|
|
295
|
+
allowedPaths.some(
|
|
296
|
+
(allowedPath) =>
|
|
297
|
+
filePath === allowedPath || filePath.startsWith(`${allowedPath}/`),
|
|
298
|
+
);
|
|
299
|
+
|
|
300
|
+
private maybeAutoApprovePrByChangeTarget = async (
|
|
301
|
+
issue: { labels: string[] },
|
|
302
|
+
approvedPrUrl: string | null,
|
|
303
|
+
): Promise<void> => {
|
|
304
|
+
if (approvedPrUrl === null) {
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
const changeTargetPaths = this.extractChangeTargetPaths(issue.labels);
|
|
308
|
+
if (changeTargetPaths.length === 0) {
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
const changedFilePaths =
|
|
312
|
+
await this.issueRepository.getPullRequestChangedFilePaths(approvedPrUrl);
|
|
313
|
+
if (changedFilePaths.length === 0) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
const allConfined = changedFilePaths.every((filePath) =>
|
|
317
|
+
this.isFilePathConfinedToAllowedPaths(filePath, changeTargetPaths),
|
|
318
|
+
);
|
|
319
|
+
if (!allConfined) {
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
await this.issueRepository.approvePullRequest(approvedPrUrl);
|
|
323
|
+
};
|
|
324
|
+
|
|
274
325
|
private collectRejections = async (
|
|
275
326
|
issue: { url: string; labels: string[]; isPr: boolean },
|
|
276
327
|
comments: { author: string; content: string }[],
|
|
@@ -90,6 +90,8 @@ export interface IssueRepository {
|
|
|
90
90
|
update: (issue: Issue, project: Project) => Promise<void>;
|
|
91
91
|
findRelatedOpenPRs: (issueUrl: string) => Promise<RelatedPullRequest[]>;
|
|
92
92
|
getOpenPullRequest: (prUrl: string) => Promise<RelatedPullRequest | null>;
|
|
93
|
+
getPullRequestChangedFilePaths: (prUrl: string) => Promise<string[]>;
|
|
94
|
+
approvePullRequest: (prUrl: string) => Promise<void>;
|
|
93
95
|
closePullRequest: (prUrl: string) => Promise<void>;
|
|
94
96
|
deletePullRequestBranch: (prUrl: string, branchName: string) => Promise<void>;
|
|
95
97
|
createCommentByUrl: (
|
|
@@ -65,6 +65,8 @@ export declare class ApiV3CheerioRestIssueRepository extends BaseGitHubRepositor
|
|
|
65
65
|
getStoryObjectMap: (project: Project, allowCacheMinutes: number) => Promise<StoryObjectMap>;
|
|
66
66
|
getOpenPullRequest: (prUrl: string) => Promise<RelatedPullRequest | null>;
|
|
67
67
|
closePullRequest: (prUrl: string) => Promise<void>;
|
|
68
|
+
getPullRequestChangedFilePaths: (prUrl: string) => Promise<string[]>;
|
|
69
|
+
approvePullRequest: (prUrl: string) => Promise<void>;
|
|
68
70
|
deletePullRequestBranch: (prUrl: string, branchName: string) => Promise<void>;
|
|
69
71
|
createCommentByUrl: (issueOrPrUrl: string, commentBody: string) => Promise<void>;
|
|
70
72
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApiV3CheerioRestIssueRepository.d.ts","sourceRoot":"","sources":["../../../../src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,kBAAkB,EACnB,MAAM,6DAA6D,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAC3D,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EACL,4BAA4B,EAC5B,WAAW,EACZ,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,2BAA2B,EAAE,MAAM,gCAAgC,CAAC;AAE7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"ApiV3CheerioRestIssueRepository.d.ts","sourceRoot":"","sources":["../../../../src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GraphqlProjectItemRepository.d.ts","sourceRoot":"","sources":["../../../../src/adapter/repositories/issue/GraphqlProjectItemRepository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAC3D,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;KACtB,EAAE,CAAC;CACL,CAAC;AACF,eAAO,MAAM,mBAAmB,OAAO,CAAC;AACxC,eAAO,MAAM,qCAAqC,MAAM,CAAC;AACzD,eAAO,MAAM,oDAAoD,OAAO,CAAC;AAczE,qBAAa,4BAA6B,SAAQ,oBAAoB;IACpE,WAAW,GACT,WAAW,MAAM,EACjB,OAAO,MAAM,EACb,gBAAgB,MAAM,EACtB,aAAa,MAAM,KAClB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAoE5B;IACF,iBAAiB,GAAU,WAAW,MAAM,KAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CA2XnE;IACF,gCAAgC,GAC9B,UAAU,MAAM,KACf,OAAO,CACR;QACE,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;KACpB,EAAE,CACJ,CAGC;IAEF,oBAAoB,GAClB,OAAO,MAAM,EACb,gBAAgB,MAAM,EACtB,aAAa,MAAM,KAClB,OAAO,CACR;QACE,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;KACpB,EAAE,CACJ,CAqJC;IACF,qBAAqB,GACnB,UAAU,MAAM,KACf,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"GraphqlProjectItemRepository.d.ts","sourceRoot":"","sources":["../../../../src/adapter/repositories/issue/GraphqlProjectItemRepository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAC3D,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;KACtB,EAAE,CAAC;CACL,CAAC;AACF,eAAO,MAAM,mBAAmB,OAAO,CAAC;AACxC,eAAO,MAAM,qCAAqC,MAAM,CAAC;AACzD,eAAO,MAAM,oDAAoD,OAAO,CAAC;AAczE,qBAAa,4BAA6B,SAAQ,oBAAoB;IACpE,WAAW,GACT,WAAW,MAAM,EACjB,OAAO,MAAM,EACb,gBAAgB,MAAM,EACtB,aAAa,MAAM,KAClB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAoE5B;IACF,iBAAiB,GAAU,WAAW,MAAM,KAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CA2XnE;IACF,gCAAgC,GAC9B,UAAU,MAAM,KACf,OAAO,CACR;QACE,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;KACpB,EAAE,CACJ,CAGC;IAEF,oBAAoB,GAClB,OAAO,MAAM,EACb,gBAAgB,MAAM,EACtB,aAAa,MAAM,KAClB,OAAO,CACR;QACE,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;KACpB,EAAE,CACJ,CAqJC;IACF,qBAAqB,GACnB,UAAU,MAAM,KACf,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CA0P5B;IACF,iBAAiB,GAAI,OAAO,MAAM,KAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAQ/D;IAEF,kBAAkB,GAChB,WAAW,MAAM,EACjB,SAAS,MAAM,EACf,QAAQ,MAAM,EACd,OACI;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAChB;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAClB;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAChB;QAAE,oBAAoB,EAAE,MAAM,CAAA;KAAE,KACnC,OAAO,CAAC,IAAI,CAAC,CAgCd;IAEF,iBAAiB,GACf,WAAW,MAAM,EACjB,SAAS,MAAM,EACf,QAAQ,MAAM,KACb,OAAO,CAAC,IAAI,CAAC,CA+Bd;IACF,sBAAsB,GACpB,SAAS,OAAO,CAAC,IAAI,CAAC,EACtB,SAAS,MAAM,EACf,OAAO,KAAK,CAAC,QAAQ,CAAC,EACtB,MAAM,MAAM,KACX,OAAO,CAAC,IAAI,CAAC,CAEd;IAEF,qBAAqB,GACnB,WAAW,MAAM,EACjB,QAAQ,MAAM,KACb,OAAO,CAAC,IAAI,CAAC,CAgCd;IAEF,+BAA+B,GAC7B,UAAU,MAAM,EAChB,WAAW,MAAM,KAChB,OAAO,CAAC,IAAI,CAAC,CASd;IAEF,iBAAiB,GACf,WAAW,MAAM,EACjB,UAAU,MAAM,KACf,OAAO,CAAC,IAAI,CAAC,CA4Dd;CACH"}
|
|
@@ -14,7 +14,7 @@ export declare class NotifyFinishedIssuePreparationUseCase {
|
|
|
14
14
|
private readonly issueCommentRepository;
|
|
15
15
|
private readonly webhookRepository;
|
|
16
16
|
private readonly issueRejectionEvaluator;
|
|
17
|
-
constructor(projectRepository: Pick<ProjectRepository, 'getByUrl'>, issueRepository: Pick<IssueRepository, 'get' | 'update' | 'updateStatus' | 'findRelatedOpenPRs' | 'getStoryObjectMap' | 'getOpenPullRequest' | 'setDependedIssueUrl'>, issueCommentRepository: Pick<IssueCommentRepository, 'getCommentsFromIssue' | 'createComment'>, webhookRepository: Pick<WebhookRepository, 'sendGetRequest'>);
|
|
17
|
+
constructor(projectRepository: Pick<ProjectRepository, 'getByUrl'>, issueRepository: Pick<IssueRepository, 'get' | 'update' | 'updateStatus' | 'findRelatedOpenPRs' | 'getStoryObjectMap' | 'getOpenPullRequest' | 'getPullRequestChangedFilePaths' | 'approvePullRequest' | 'setDependedIssueUrl'>, issueCommentRepository: Pick<IssueCommentRepository, 'getCommentsFromIssue' | 'createComment'>, webhookRepository: Pick<WebhookRepository, 'sendGetRequest'>);
|
|
18
18
|
run: (params: {
|
|
19
19
|
projectUrl: string;
|
|
20
20
|
issueUrl: string;
|
|
@@ -23,6 +23,9 @@ export declare class NotifyFinishedIssuePreparationUseCase {
|
|
|
23
23
|
allowedIssueAuthors?: string[] | null;
|
|
24
24
|
}) => Promise<void>;
|
|
25
25
|
private isAuthorTrusted;
|
|
26
|
+
private extractChangeTargetPaths;
|
|
27
|
+
private isFilePathConfinedToAllowedPaths;
|
|
28
|
+
private maybeAutoApprovePrByChangeTarget;
|
|
26
29
|
private collectRejections;
|
|
27
30
|
private reportBodyHasNextStep;
|
|
28
31
|
private setDependedIssueUrlForAllOpenPRs;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NotifyFinishedIssuePreparationUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/NotifyFinishedIssuePreparationUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AACrF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAY3E,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,QAAQ,EAAE,MAAM;CAI7B;AACD,qBAAa,uBAAwB,SAAQ,KAAK;gBAE9C,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,cAAc,EAAE,MAAM,GAAG,IAAI;CAOhC;AAMD,qBAAa,qCAAqC;IAI9C,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,eAAe;
|
|
1
|
+
{"version":3,"file":"NotifyFinishedIssuePreparationUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/NotifyFinishedIssuePreparationUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AACrF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAY3E,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,QAAQ,EAAE,MAAM;CAI7B;AACD,qBAAa,uBAAwB,SAAQ,KAAK;gBAE9C,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,cAAc,EAAE,MAAM,GAAG,IAAI;CAOhC;AAMD,qBAAa,qCAAqC;IAI9C,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAYhC,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IAIvC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IApBpC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAA0B;gBAG/C,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,EAAE,UAAU,CAAC,EACtD,eAAe,EAAE,IAAI,CACpC,eAAe,EACb,KAAK,GACL,QAAQ,GACR,cAAc,GACd,oBAAoB,GACpB,mBAAmB,GACnB,oBAAoB,GACpB,gCAAgC,GAChC,oBAAoB,GACpB,qBAAqB,CACxB,EACgB,sBAAsB,EAAE,IAAI,CAC3C,sBAAsB,EACtB,sBAAsB,GAAG,eAAe,CACzC,EACgB,iBAAiB,EAAE,IAAI,CACtC,iBAAiB,EACjB,gBAAgB,CACjB;IAKH,GAAG,GAAU,QAAQ;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,sBAAsB,EAAE,MAAM,CAAC;QAC/B,iCAAiC,EAAE,MAAM,GAAG,IAAI,CAAC;QACjD,mBAAmB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;KACvC,KAAG,OAAO,CAAC,IAAI,CAAC,CAmMf;IAEF,OAAO,CAAC,eAAe,CAIgD;IAEvE,OAAO,CAAC,wBAAwB,CAY9B;IAEF,OAAO,CAAC,gCAAgC,CAOpC;IAEJ,OAAO,CAAC,gCAAgC,CAuBtC;IAEF,OAAO,CAAC,iBAAiB,CA8BvB;IAEF,OAAO,CAAC,qBAAqB,CAuB3B;IAEF,OAAO,CAAC,gCAAgC,CAiBtC;IAEF,OAAO,CAAC,uBAAuB,CAQ7B;IAEF,OAAO,CAAC,+BAA+B,CAkCrC;CACH"}
|
|
@@ -53,6 +53,8 @@ export interface IssueRepository {
|
|
|
53
53
|
update: (issue: Issue, project: Project) => Promise<void>;
|
|
54
54
|
findRelatedOpenPRs: (issueUrl: string) => Promise<RelatedPullRequest[]>;
|
|
55
55
|
getOpenPullRequest: (prUrl: string) => Promise<RelatedPullRequest | null>;
|
|
56
|
+
getPullRequestChangedFilePaths: (prUrl: string) => Promise<string[]>;
|
|
57
|
+
approvePullRequest: (prUrl: string) => Promise<void>;
|
|
56
58
|
closePullRequest: (prUrl: string) => Promise<void>;
|
|
57
59
|
deletePullRequestBranch: (prUrl: string, branchName: string) => Promise<void>;
|
|
58
60
|
createCommentByUrl: (issueOrPrUrl: string, commentBody: string) => Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IssueRepository.d.ts","sourceRoot":"","sources":["../../../../src/domain/usecases/adapter-interfaces/IssueRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,2BAA2B,EAAE,OAAO,CAAC;IACrC,iBAAiB,EAAE,OAAO,CAAC;IAC3B,yBAAyB,EAAE,MAAM,EAAE,CAAC;CACrC,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,CACZ,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,EACxB,iBAAiB,EAAE,MAAM,KACtB,OAAO,CAAC;QAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACtD,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IACtD,cAAc,EAAE,CACd,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EAC3B,MAAM,EAAE,KAAK,EAAE,KACZ,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,WAAW,EAAE,CAAC,KAAK,EAAE;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,cAAc,EAAE,MAAM,CAAC;QACvB,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;QACtB,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;QAClC,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,KAAK,OAAO,CACX;QACE,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,EAAE,CACJ,CAAC;IACF,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,oBAAoB,EAAE,CACpB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,IAAI,KACP,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,oBAAoB,EAAE,CACpB,OAAO,EAAE,OAAO,GAAG;QACjB,cAAc,EAAE,WAAW,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC;KACxD,EACD,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,MAAM,KACT,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,sBAAsB,EAAE,CACtB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,MAAM,KACT,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,WAAW,EAAE,CACX,OAAO,EAAE,OAAO,GAAG;QAAE,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;KAAE,EAC3D,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC,KACvB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,YAAY,EAAE,CACZ,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,iBAAiB,EAAE,CACjB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,KAAK,KACT,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,YAAY,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,kBAAkB,EAAE,CAClB,KAAK,EAAE,KAAK,EACZ,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,KAC3B,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,GAAG,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IACnE,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,kBAAkB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAC;IACxE,kBAAkB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;IAC1E,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,uBAAuB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,kBAAkB,EAAE,CAClB,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,KAChB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,YAAY,EAAE,CACZ,OAAO,EAAE,OAAO,EAChB,iBAAiB,EAAE,MAAM,KACtB,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;IACtB,iBAAiB,EAAE,CACjB,OAAO,EAAE,OAAO,EAChB,iBAAiB,EAAE,MAAM,KACtB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,iBAAiB,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzE,mBAAmB,EAAE,CACnB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB"}
|
|
1
|
+
{"version":3,"file":"IssueRepository.d.ts","sourceRoot":"","sources":["../../../../src/domain/usecases/adapter-interfaces/IssueRepository.ts"],"names":[],"mappings":"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"}
|