@paysdoc/devplatform 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/LICENSE +21 -0
- package/README.md +122 -0
- package/dist/git/bootstrapIdentity.d.ts +50 -0
- package/dist/git/bootstrapIdentity.d.ts.map +1 -0
- package/dist/git/bootstrapIdentity.js +72 -0
- package/dist/git/bootstrapIdentity.js.map +1 -0
- package/dist/git/branchOps.d.ts +27 -0
- package/dist/git/branchOps.d.ts.map +1 -0
- package/dist/git/branchOps.js +91 -0
- package/dist/git/branchOps.js.map +1 -0
- package/dist/git/claimOps.d.ts +40 -0
- package/dist/git/claimOps.d.ts.map +1 -0
- package/dist/git/claimOps.js +44 -0
- package/dist/git/claimOps.js.map +1 -0
- package/dist/git/commitOps.d.ts +35 -0
- package/dist/git/commitOps.d.ts.map +1 -0
- package/dist/git/commitOps.js +131 -0
- package/dist/git/commitOps.js.map +1 -0
- package/dist/git/consoleLogger.d.ts +8 -0
- package/dist/git/consoleLogger.d.ts.map +1 -0
- package/dist/git/consoleLogger.js +9 -0
- package/dist/git/consoleLogger.js.map +1 -0
- package/dist/git/gitContext.d.ts +150 -0
- package/dist/git/gitContext.d.ts.map +1 -0
- package/dist/git/gitContext.js +405 -0
- package/dist/git/gitContext.js.map +1 -0
- package/dist/git/gitReadOps.d.ts +33 -0
- package/dist/git/gitReadOps.d.ts.map +1 -0
- package/dist/git/gitReadOps.js +38 -0
- package/dist/git/gitReadOps.js.map +1 -0
- package/dist/git/index.d.ts +49 -0
- package/dist/git/index.d.ts.map +1 -0
- package/dist/git/index.js +44 -0
- package/dist/git/index.js.map +1 -0
- package/dist/git/processCleanup.d.ts +7 -0
- package/dist/git/processCleanup.d.ts.map +1 -0
- package/dist/git/processCleanup.js +45 -0
- package/dist/git/processCleanup.js.map +1 -0
- package/dist/git/remoteOps.d.ts +25 -0
- package/dist/git/remoteOps.d.ts.map +1 -0
- package/dist/git/remoteOps.js +30 -0
- package/dist/git/remoteOps.js.map +1 -0
- package/dist/git/repoWorkspace.d.ts +72 -0
- package/dist/git/repoWorkspace.d.ts.map +1 -0
- package/dist/git/repoWorkspace.js +85 -0
- package/dist/git/repoWorkspace.js.map +1 -0
- package/dist/git/types.d.ts +182 -0
- package/dist/git/types.d.ts.map +1 -0
- package/dist/git/types.js +10 -0
- package/dist/git/types.js.map +1 -0
- package/dist/git/workingDirectoryGuard.d.ts +39 -0
- package/dist/git/workingDirectoryGuard.d.ts.map +1 -0
- package/dist/git/workingDirectoryGuard.js +53 -0
- package/dist/git/workingDirectoryGuard.js.map +1 -0
- package/dist/git/worktreeCreateOps.d.ts +45 -0
- package/dist/git/worktreeCreateOps.d.ts.map +1 -0
- package/dist/git/worktreeCreateOps.js +208 -0
- package/dist/git/worktreeCreateOps.js.map +1 -0
- package/dist/git/worktreeProbeOps.d.ts +17 -0
- package/dist/git/worktreeProbeOps.d.ts.map +1 -0
- package/dist/git/worktreeProbeOps.js +66 -0
- package/dist/git/worktreeProbeOps.js.map +1 -0
- package/dist/git/worktreeQueryOps.d.ts +45 -0
- package/dist/git/worktreeQueryOps.d.ts.map +1 -0
- package/dist/git/worktreeQueryOps.js +129 -0
- package/dist/git/worktreeQueryOps.js.map +1 -0
- package/dist/git/worktreeRemoveOps.d.ts +27 -0
- package/dist/git/worktreeRemoveOps.d.ts.map +1 -0
- package/dist/git/worktreeRemoveOps.js +132 -0
- package/dist/git/worktreeRemoveOps.js.map +1 -0
- package/dist/git/worktreeResetOps.d.ts +18 -0
- package/dist/git/worktreeResetOps.d.ts.map +1 -0
- package/dist/git/worktreeResetOps.js +68 -0
- package/dist/git/worktreeResetOps.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/forgeProviders.d.ts +72 -0
- package/dist/providers/forgeProviders.d.ts.map +1 -0
- package/dist/providers/forgeProviders.js +112 -0
- package/dist/providers/forgeProviders.js.map +1 -0
- package/dist/providers/github/appAuth.d.ts +70 -0
- package/dist/providers/github/appAuth.d.ts.map +1 -0
- package/dist/providers/github/appAuth.js +243 -0
- package/dist/providers/github/appAuth.js.map +1 -0
- package/dist/providers/github/cloneUrl.d.ts +12 -0
- package/dist/providers/github/cloneUrl.d.ts.map +1 -0
- package/dist/providers/github/cloneUrl.js +20 -0
- package/dist/providers/github/cloneUrl.js.map +1 -0
- package/dist/providers/github/commands/boardCommands.d.ts +22 -0
- package/dist/providers/github/commands/boardCommands.d.ts.map +1 -0
- package/dist/providers/github/commands/boardCommands.js +66 -0
- package/dist/providers/github/commands/boardCommands.js.map +1 -0
- package/dist/providers/github/commands/issueCommands.d.ts +21 -0
- package/dist/providers/github/commands/issueCommands.d.ts.map +1 -0
- package/dist/providers/github/commands/issueCommands.js +50 -0
- package/dist/providers/github/commands/issueCommands.js.map +1 -0
- package/dist/providers/github/commands/labelCommands.d.ts +3 -0
- package/dist/providers/github/commands/labelCommands.d.ts.map +1 -0
- package/dist/providers/github/commands/labelCommands.js +8 -0
- package/dist/providers/github/commands/labelCommands.js.map +1 -0
- package/dist/providers/github/commands/prCommands.d.ts +14 -0
- package/dist/providers/github/commands/prCommands.d.ts.map +1 -0
- package/dist/providers/github/commands/prCommands.js +46 -0
- package/dist/providers/github/commands/prCommands.js.map +1 -0
- package/dist/providers/github/commands/secretCommands.d.ts +2 -0
- package/dist/providers/github/commands/secretCommands.d.ts.map +1 -0
- package/dist/providers/github/commands/secretCommands.js +5 -0
- package/dist/providers/github/commands/secretCommands.js.map +1 -0
- package/dist/providers/github/contextBinding.d.ts +11 -0
- package/dist/providers/github/contextBinding.d.ts.map +1 -0
- package/dist/providers/github/contextBinding.js +15 -0
- package/dist/providers/github/contextBinding.js.map +1 -0
- package/dist/providers/github/domain/issue.d.ts +94 -0
- package/dist/providers/github/domain/issue.d.ts.map +1 -0
- package/dist/providers/github/domain/issue.js +7 -0
- package/dist/providers/github/domain/issue.js.map +1 -0
- package/dist/providers/github/domain/pullRequest.d.ts +55 -0
- package/dist/providers/github/domain/pullRequest.d.ts.map +1 -0
- package/dist/providers/github/domain/pullRequest.js +9 -0
- package/dist/providers/github/domain/pullRequest.js.map +1 -0
- package/dist/providers/github/ghAuthToken.d.ts +28 -0
- package/dist/providers/github/ghAuthToken.d.ts.map +1 -0
- package/dist/providers/github/ghAuthToken.js +39 -0
- package/dist/providers/github/ghAuthToken.js.map +1 -0
- package/dist/providers/github/ghCommandRunner.d.ts +20 -0
- package/dist/providers/github/ghCommandRunner.d.ts.map +1 -0
- package/dist/providers/github/ghCommandRunner.js +21 -0
- package/dist/providers/github/ghCommandRunner.js.map +1 -0
- package/dist/providers/github/ghIssueApi.d.ts +29 -0
- package/dist/providers/github/ghIssueApi.d.ts.map +1 -0
- package/dist/providers/github/ghIssueApi.js +37 -0
- package/dist/providers/github/ghIssueApi.js.map +1 -0
- package/dist/providers/github/ghIssueParsers.d.ts +28 -0
- package/dist/providers/github/ghIssueParsers.d.ts.map +1 -0
- package/dist/providers/github/ghIssueParsers.js +105 -0
- package/dist/providers/github/ghIssueParsers.js.map +1 -0
- package/dist/providers/github/ghPrApi.d.ts +27 -0
- package/dist/providers/github/ghPrApi.d.ts.map +1 -0
- package/dist/providers/github/ghPrApi.js +32 -0
- package/dist/providers/github/ghPrApi.js.map +1 -0
- package/dist/providers/github/ghPrParsers.d.ts +57 -0
- package/dist/providers/github/ghPrParsers.d.ts.map +1 -0
- package/dist/providers/github/ghPrParsers.js +135 -0
- package/dist/providers/github/ghPrParsers.js.map +1 -0
- package/dist/providers/github/ghRepoApi.d.ts +33 -0
- package/dist/providers/github/ghRepoApi.d.ts.map +1 -0
- package/dist/providers/github/ghRepoApi.js +89 -0
- package/dist/providers/github/ghRepoApi.js.map +1 -0
- package/dist/providers/github/githubBoardManager.d.ts +39 -0
- package/dist/providers/github/githubBoardManager.d.ts.map +1 -0
- package/dist/providers/github/githubBoardManager.js +166 -0
- package/dist/providers/github/githubBoardManager.js.map +1 -0
- package/dist/providers/github/githubCodeHost.d.ts +73 -0
- package/dist/providers/github/githubCodeHost.d.ts.map +1 -0
- package/dist/providers/github/githubCodeHost.js +217 -0
- package/dist/providers/github/githubCodeHost.js.map +1 -0
- package/dist/providers/github/githubIdentity.d.ts +51 -0
- package/dist/providers/github/githubIdentity.d.ts.map +1 -0
- package/dist/providers/github/githubIdentity.js +110 -0
- package/dist/providers/github/githubIdentity.js.map +1 -0
- package/dist/providers/github/githubIssueTracker.d.ts +69 -0
- package/dist/providers/github/githubIssueTracker.d.ts.map +1 -0
- package/dist/providers/github/githubIssueTracker.js +209 -0
- package/dist/providers/github/githubIssueTracker.js.map +1 -0
- package/dist/providers/github/githubTokenProvider.d.ts +41 -0
- package/dist/providers/github/githubTokenProvider.d.ts.map +1 -0
- package/dist/providers/github/githubTokenProvider.js +51 -0
- package/dist/providers/github/githubTokenProvider.js.map +1 -0
- package/dist/providers/github/index.d.ts +10 -0
- package/dist/providers/github/index.d.ts.map +1 -0
- package/dist/providers/github/index.js +5 -0
- package/dist/providers/github/index.js.map +1 -0
- package/dist/providers/github/mappers.d.ts +40 -0
- package/dist/providers/github/mappers.d.ts.map +1 -0
- package/dist/providers/github/mappers.js +103 -0
- package/dist/providers/github/mappers.js.map +1 -0
- package/dist/providers/github/tokenResolver.d.ts +37 -0
- package/dist/providers/github/tokenResolver.d.ts.map +1 -0
- package/dist/providers/github/tokenResolver.js +43 -0
- package/dist/providers/github/tokenResolver.js.map +1 -0
- package/dist/providers/gitlab/gitlabApiClient.d.ts +45 -0
- package/dist/providers/gitlab/gitlabApiClient.d.ts.map +1 -0
- package/dist/providers/gitlab/gitlabApiClient.js +95 -0
- package/dist/providers/gitlab/gitlabApiClient.js.map +1 -0
- package/dist/providers/gitlab/gitlabBoardManager.d.ts +11 -0
- package/dist/providers/gitlab/gitlabBoardManager.d.ts.map +1 -0
- package/dist/providers/gitlab/gitlabBoardManager.js +27 -0
- package/dist/providers/gitlab/gitlabBoardManager.js.map +1 -0
- package/dist/providers/gitlab/gitlabCodeHost.d.ts +49 -0
- package/dist/providers/gitlab/gitlabCodeHost.d.ts.map +1 -0
- package/dist/providers/gitlab/gitlabCodeHost.js +109 -0
- package/dist/providers/gitlab/gitlabCodeHost.js.map +1 -0
- package/dist/providers/gitlab/gitlabTypes.d.ts +46 -0
- package/dist/providers/gitlab/gitlabTypes.d.ts.map +1 -0
- package/dist/providers/gitlab/gitlabTypes.js +6 -0
- package/dist/providers/gitlab/gitlabTypes.js.map +1 -0
- package/dist/providers/gitlab/index.d.ts +5 -0
- package/dist/providers/gitlab/index.d.ts.map +1 -0
- package/dist/providers/gitlab/index.js +4 -0
- package/dist/providers/gitlab/index.js.map +1 -0
- package/dist/providers/gitlab/mappers.d.ts +26 -0
- package/dist/providers/gitlab/mappers.d.ts.map +1 -0
- package/dist/providers/gitlab/mappers.js +63 -0
- package/dist/providers/gitlab/mappers.js.map +1 -0
- package/dist/providers/index.d.ts +7 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +7 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/jira/adfConverter.d.ts +32 -0
- package/dist/providers/jira/adfConverter.d.ts.map +1 -0
- package/dist/providers/jira/adfConverter.js +144 -0
- package/dist/providers/jira/adfConverter.js.map +1 -0
- package/dist/providers/jira/index.d.ts +8 -0
- package/dist/providers/jira/index.d.ts.map +1 -0
- package/dist/providers/jira/index.js +5 -0
- package/dist/providers/jira/index.js.map +1 -0
- package/dist/providers/jira/jiraApiClient.d.ts +42 -0
- package/dist/providers/jira/jiraApiClient.d.ts.map +1 -0
- package/dist/providers/jira/jiraApiClient.js +84 -0
- package/dist/providers/jira/jiraApiClient.js.map +1 -0
- package/dist/providers/jira/jiraBoardManager.d.ts +11 -0
- package/dist/providers/jira/jiraBoardManager.d.ts.map +1 -0
- package/dist/providers/jira/jiraBoardManager.js +27 -0
- package/dist/providers/jira/jiraBoardManager.js.map +1 -0
- package/dist/providers/jira/jiraIssueTracker.d.ts +53 -0
- package/dist/providers/jira/jiraIssueTracker.d.ts.map +1 -0
- package/dist/providers/jira/jiraIssueTracker.js +231 -0
- package/dist/providers/jira/jiraIssueTracker.js.map +1 -0
- package/dist/providers/jira/jiraTypes.d.ts +61 -0
- package/dist/providers/jira/jiraTypes.d.ts.map +1 -0
- package/dist/providers/jira/jiraTypes.js +6 -0
- package/dist/providers/jira/jiraTypes.js.map +1 -0
- package/dist/providers/types.d.ts +271 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +52 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/providers/workspaceValidation.d.ts +18 -0
- package/dist/providers/workspaceValidation.d.ts.map +1 -0
- package/dist/providers/workspaceValidation.js +37 -0
- package/dist/providers/workspaceValidation.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub implementation of the CodeHost interface.
|
|
3
|
+
*
|
|
4
|
+
* Binds `createGhRepoApi(ctx)` once at construction, over a `GitContext` the
|
|
5
|
+
* caller already holds. Every method reproduces the command, parse, error
|
|
6
|
+
* policy and log line of its absorbed legacy free function
|
|
7
|
+
* (`adws/github/prApi.ts`) exactly, logging through the injected `Logger`
|
|
8
|
+
* port instead of `adws/core`'s `log`.
|
|
9
|
+
*/
|
|
10
|
+
import { consoleLogger } from '../../git/index.js';
|
|
11
|
+
import { createGhRepoApi } from './ghRepoApi.js';
|
|
12
|
+
import { assertContextBoundTo } from './contextBinding.js';
|
|
13
|
+
import { parsePRDetails, parsePRReviews, parsePRLineComments, parsePRListItems, selectPreferredPR, parsePRApprovalState, } from './ghPrParsers.js';
|
|
14
|
+
import { mapPRDetailsToPullRequest, mapPRReviewCommentToReviewComment, mapPRListItemToPullRequest, mapRawPRToSummary, } from './mappers.js';
|
|
15
|
+
import { validateRepoIdentifier, } from '../types.js';
|
|
16
|
+
/** `error.stderr` when present (child-process failures), else `String(error)`. */
|
|
17
|
+
function stderrOf(error) {
|
|
18
|
+
return error.stderr || String(error);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* GitHub-specific implementation of the CodeHost interface. Bound to a
|
|
22
|
+
* specific repository and `GitContext` at construction time.
|
|
23
|
+
*/
|
|
24
|
+
export class GitHubCodeHost {
|
|
25
|
+
repoId;
|
|
26
|
+
gh;
|
|
27
|
+
logger;
|
|
28
|
+
canApprove;
|
|
29
|
+
/** Memoised authenticated-user login: `undefined` = not yet asked, `null` = failed. */
|
|
30
|
+
authenticatedUserMemo;
|
|
31
|
+
constructor(ctx, repoId, deps = {}) {
|
|
32
|
+
this.repoId = repoId;
|
|
33
|
+
assertContextBoundTo(ctx, repoId, 'createGitHubCodeHost');
|
|
34
|
+
this.gh = createGhRepoApi(ctx);
|
|
35
|
+
this.logger = deps.logger ?? consoleLogger;
|
|
36
|
+
this.canApprove = deps.canApprovePullRequests;
|
|
37
|
+
}
|
|
38
|
+
/** Returns the bound RepoIdentifier. */
|
|
39
|
+
getRepoIdentifier() {
|
|
40
|
+
return this.repoId;
|
|
41
|
+
}
|
|
42
|
+
getDefaultBranch() {
|
|
43
|
+
return this.gh.defaultBranch();
|
|
44
|
+
}
|
|
45
|
+
/** Fetches PR details and maps to PullRequest. */
|
|
46
|
+
fetchPullRequest(prNumber) {
|
|
47
|
+
try {
|
|
48
|
+
return mapPRDetailsToPullRequest(parsePRDetails(this.gh.fetchPRDetails(prNumber)));
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
throw new Error(`Failed to fetch PR #${prNumber}: ${error}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** Posts a comment on the specified PR. */
|
|
55
|
+
commentOnPullRequest(prNumber, body) {
|
|
56
|
+
try {
|
|
57
|
+
this.gh.commentOnPR(prNumber, body);
|
|
58
|
+
this.logger(`Commented on PR #${prNumber}`, 'success');
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
this.logger(`Failed to comment on PR: ${error}`, 'error');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
fetchLineComments(prNumber) {
|
|
65
|
+
try {
|
|
66
|
+
return parsePRLineComments(this.gh.fetchPRReviewComments(prNumber));
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
this.logger(`Failed to fetch PR review comments: ${error}`, 'error');
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
fetchReviewBodies(prNumber) {
|
|
74
|
+
try {
|
|
75
|
+
return parsePRReviews(this.gh.fetchPRReviews(prNumber));
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
this.logger(`Failed to fetch PR reviews: ${error}`, 'error');
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/** Fetches review comments (line-level + review-body) and maps to ReviewComment[]. */
|
|
83
|
+
fetchReviewComments(prNumber) {
|
|
84
|
+
const { owner, repo } = this.repoId;
|
|
85
|
+
this.logger(`Fetching PR review comments for ${owner}/${repo}#${prNumber}`);
|
|
86
|
+
const lineComments = this.fetchLineComments(prNumber);
|
|
87
|
+
this.logger(`Fetched ${lineComments.length} line-level comments for ${owner}/${repo}#${prNumber}`);
|
|
88
|
+
const reviewBodyComments = this.fetchReviewBodies(prNumber);
|
|
89
|
+
this.logger(`Fetched ${reviewBodyComments.length} review-body comments for ${owner}/${repo}#${prNumber}`);
|
|
90
|
+
const allComments = [...lineComments, ...reviewBodyComments];
|
|
91
|
+
this.logger(`Total: ${allComments.length} comments for ${owner}/${repo}#${prNumber}`);
|
|
92
|
+
return allComments.map(mapPRReviewCommentToReviewComment);
|
|
93
|
+
}
|
|
94
|
+
/** Lists open PRs and maps to PullRequest[]. */
|
|
95
|
+
listOpenPullRequests() {
|
|
96
|
+
try {
|
|
97
|
+
return parsePRListItems(this.gh.fetchPRList()).map(mapPRListItemToPullRequest);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
this.logger(`Failed to fetch PR list: ${error}`, 'error');
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Creates a pull request via `gh pr create` with the provided title and body.
|
|
106
|
+
* Reuses an existing open PR on the branch, if one is found, rather than
|
|
107
|
+
* opening a second. Returns the PR URL and number.
|
|
108
|
+
*/
|
|
109
|
+
createPullRequest(options) {
|
|
110
|
+
try {
|
|
111
|
+
const existingJson = this.gh.findPRByBranch(options.sourceBranch);
|
|
112
|
+
const parsed = JSON.parse(existingJson);
|
|
113
|
+
const open = parsed.filter((p) => p.state === 'OPEN');
|
|
114
|
+
if (open.length > 0) {
|
|
115
|
+
const pr = open[0];
|
|
116
|
+
const url = `https://github.com/${this.repoId.owner}/${this.repoId.repo}/pull/${pr.number}`;
|
|
117
|
+
this.logger(`Existing PR #${pr.number} found for branch ${options.sourceBranch}, reusing`, 'info');
|
|
118
|
+
return { url, number: pr.number };
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// If the check fails, fall through to normal PR creation
|
|
123
|
+
}
|
|
124
|
+
const prUrl = this.gh.createPR(options.title, options.body, options.sourceBranch, options.targetBranch);
|
|
125
|
+
const numberMatch = prUrl.match(/\/pull\/(\d+)$/);
|
|
126
|
+
if (!numberMatch) {
|
|
127
|
+
throw new Error(`Could not extract PR number from URL: ${prUrl}`);
|
|
128
|
+
}
|
|
129
|
+
return { url: prUrl, number: parseInt(numberMatch[1], 10) };
|
|
130
|
+
}
|
|
131
|
+
/** Finds the PR for a branch (open, or most-recently-updated when none are open); null if none. */
|
|
132
|
+
findPullRequestByBranch(branchName) {
|
|
133
|
+
try {
|
|
134
|
+
const pr = selectPreferredPR(JSON.parse(this.gh.findPRByBranch(branchName)));
|
|
135
|
+
return pr ? mapRawPRToSummary(pr) : null;
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/** True when the PR has at least one qualifying approval. */
|
|
142
|
+
isPullRequestApproved(prNumber) {
|
|
143
|
+
try {
|
|
144
|
+
return parsePRApprovalState(this.gh.prApprovalState(prNumber));
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
this.logger(`fetchPRApprovalState: failed to fetch reviews for PR #${prNumber}: ${error}`, 'warn');
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/** Approves a PR under the bound identity. */
|
|
152
|
+
approvePullRequest(prNumber) {
|
|
153
|
+
try {
|
|
154
|
+
this.gh.approvePR(prNumber);
|
|
155
|
+
this.logger(`Approved PR #${prNumber} in ${this.repoId.owner}/${this.repoId.repo}`, 'success');
|
|
156
|
+
return { success: true };
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
const stderr = stderrOf(error);
|
|
160
|
+
this.logger(`Failed to approve PR #${prNumber}: ${stderr}`, 'error');
|
|
161
|
+
return { success: false, error: stderr };
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/** Merges a PR. */
|
|
165
|
+
mergePullRequest(prNumber) {
|
|
166
|
+
try {
|
|
167
|
+
this.gh.mergePR(prNumber);
|
|
168
|
+
this.logger(`Merged PR #${prNumber} in ${this.repoId.owner}/${this.repoId.repo}`, 'success');
|
|
169
|
+
return { success: true };
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
const stderr = stderrOf(error);
|
|
173
|
+
this.logger(`Failed to merge PR #${prNumber}: ${stderr}`, 'error');
|
|
174
|
+
return { success: false, error: stderr };
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/** Sets a repo secret (e.g. GitHub Actions). */
|
|
178
|
+
setSecret(name, value) {
|
|
179
|
+
this.gh.setSecret(name, value);
|
|
180
|
+
}
|
|
181
|
+
/** Merged PRs, newest first, at most `limit`. Throws on failure. */
|
|
182
|
+
listMergedPullRequests(limit) {
|
|
183
|
+
return JSON.parse(this.gh.fetchMergedPRs(limit));
|
|
184
|
+
}
|
|
185
|
+
/** Every PR of the repository (open, closed and merged). Throws on failure — callers own the swallow policy. */
|
|
186
|
+
listPullRequests() {
|
|
187
|
+
return JSON.parse(this.gh.fetchAllPRs());
|
|
188
|
+
}
|
|
189
|
+
/** Login the code host's commands run as; memoised per instance, one warning on failure. */
|
|
190
|
+
getAuthenticatedUser() {
|
|
191
|
+
if (this.authenticatedUserMemo !== undefined)
|
|
192
|
+
return this.authenticatedUserMemo;
|
|
193
|
+
try {
|
|
194
|
+
const login = JSON.parse(this.gh.authenticatedUser()).login;
|
|
195
|
+
this.authenticatedUserMemo = login || null;
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
this.logger(`Could not determine authenticated GitHub user: ${error}`, 'warn');
|
|
199
|
+
this.authenticatedUserMemo = null;
|
|
200
|
+
}
|
|
201
|
+
return this.authenticatedUserMemo;
|
|
202
|
+
}
|
|
203
|
+
/** True when the injected capability seam says this identity can approve PRs; `false` by default. */
|
|
204
|
+
canApprovePullRequests() {
|
|
205
|
+
return this.canApprove?.() ?? false;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Factory function that creates a GitHubCodeHost bound to the given
|
|
210
|
+
* `GitContext` and repository. Validates the RepoIdentifier and refuses a
|
|
211
|
+
* context bound to a different owner/repo before construction.
|
|
212
|
+
*/
|
|
213
|
+
export function createGitHubCodeHost(ctx, repoId, deps = {}) {
|
|
214
|
+
validateRepoIdentifier(repoId);
|
|
215
|
+
return new GitHubCodeHost(ctx, repoId, deps);
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=githubCodeHost.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"githubCodeHost.js","sourceRoot":"","sources":["../../../src/providers/github/githubCodeHost.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub identity conventions — the forge half of bootstrap identity
|
|
3
|
+
* resolution (issue #793, PRD story 15). Owns GitHub naming conventions on
|
|
4
|
+
* behalf of the core: remote-URL parsing (including the SCP-style
|
|
5
|
+
* `git@github.com:owner/repo` form) and GitHub App bot-identity derivation.
|
|
6
|
+
*
|
|
7
|
+
* Composes the core's generic readers (`readOriginRemoteUrl`,
|
|
8
|
+
* `readEnvGitIdentity`, `readGitConfigIdentity`) rather than shelling out
|
|
9
|
+
* itself — after #792 only `adws/gitContext` may run a git command.
|
|
10
|
+
*/
|
|
11
|
+
import type { GitIdentity } from '../../git/types.js';
|
|
12
|
+
import type { GitConfigIdentityDeps } from '../../git/bootstrapIdentity.js';
|
|
13
|
+
import { type RepoIdentifier } from '../types.js';
|
|
14
|
+
export interface BootstrapIdentityDeps extends GitConfigIdentityDeps {
|
|
15
|
+
isAppConfigured?: () => boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Parses a `RepoIdentifier` out of a GitHub remote URL (HTTPS or SSH).
|
|
19
|
+
* Returns null when the URL is not a parseable GitHub remote, leaving the
|
|
20
|
+
* error contract to each caller.
|
|
21
|
+
*
|
|
22
|
+
* Pure — the single source of truth for GitHub remote-URL parsing.
|
|
23
|
+
*/
|
|
24
|
+
export declare function parseGitHubRemoteUrl(remoteUrl: string): RepoIdentifier | null;
|
|
25
|
+
/**
|
|
26
|
+
* Reads the local git remote URL (through the core's `readOriginRemoteUrl`)
|
|
27
|
+
* and parses owner/repo from it. Supports both HTTPS and SSH GitHub URL
|
|
28
|
+
* formats. Throws if the remote URL cannot be parsed.
|
|
29
|
+
*
|
|
30
|
+
* The try/catch spans BOTH the core read and the parse, so a non-GitHub
|
|
31
|
+
* remote's inner `Could not parse GitHub URL: …` message is still wrapped
|
|
32
|
+
* in the same outer `Failed to get repo info: …` a merged `@adw-779`
|
|
33
|
+
* scenario asserts on.
|
|
34
|
+
*/
|
|
35
|
+
export declare function readLocalRepoInfo(cwd?: string): RepoIdentifier;
|
|
36
|
+
/** The built-in default when nothing else resolves — deliberately forge-shaped, and deliberately not in the core (issue #793). */
|
|
37
|
+
export declare const ADW_BOT_FALLBACK_IDENTITY: GitIdentity;
|
|
38
|
+
/**
|
|
39
|
+
* Resolves a complete git author/committer identity before a GitContext exists.
|
|
40
|
+
* Resolution order:
|
|
41
|
+
* 1. GitHub App bot identity (if App configured)
|
|
42
|
+
* 2. GIT_AUTHOR_* / GIT_COMMITTER_* env vars (the core's `readEnvGitIdentity`)
|
|
43
|
+
* 3. `git config user.name / user.email` (the core's `readGitConfigIdentity`)
|
|
44
|
+
* 4. Built-in ADW Bot default (never returns empty fields)
|
|
45
|
+
*
|
|
46
|
+
* Same exported name, same deps shape and defaults as the pre-#793 resolver
|
|
47
|
+
* this replaces, so every call site and every existing assertion survives
|
|
48
|
+
* unchanged.
|
|
49
|
+
*/
|
|
50
|
+
export declare function resolveBootstrapGitIdentity(deps?: BootstrapIdentityDeps): GitIdentity;
|
|
51
|
+
//# sourceMappingURL=githubIdentity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"githubIdentity.d.ts","sourceRoot":"","sources":["../../../src/providers/github/githubIdentity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAC5E,OAAO,EAAY,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAM5D,MAAM,WAAW,qBAAsB,SAAQ,qBAAqB;IAClE,eAAe,CAAC,EAAE,MAAM,OAAO,CAAC;CACjC;AAoBD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAK7E;AAMD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,cAAc,CAW9D;AAMD,kIAAkI;AAClI,eAAO,MAAM,yBAAyB,EAAE,WAKvC,CAAC;AASF;;;;;;;;;;;GAWG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,GAAE,qBAA0B,GAAG,WAAW,CAiBzF"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub identity conventions — the forge half of bootstrap identity
|
|
3
|
+
* resolution (issue #793, PRD story 15). Owns GitHub naming conventions on
|
|
4
|
+
* behalf of the core: remote-URL parsing (including the SCP-style
|
|
5
|
+
* `git@github.com:owner/repo` form) and GitHub App bot-identity derivation.
|
|
6
|
+
*
|
|
7
|
+
* Composes the core's generic readers (`readOriginRemoteUrl`,
|
|
8
|
+
* `readEnvGitIdentity`, `readGitConfigIdentity`) rather than shelling out
|
|
9
|
+
* itself — after #792 only `adws/gitContext` may run a git command.
|
|
10
|
+
*/
|
|
11
|
+
import { readOriginRemoteUrl, readEnvGitIdentity, readGitConfigIdentity } from '../../git/bootstrapIdentity.js';
|
|
12
|
+
import { Platform } from '../types.js';
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// parseGitHubRemoteUrl
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
/**
|
|
17
|
+
* HTTPS-style GitHub remote: `https://github.com/owner/repo[.git][/]`.
|
|
18
|
+
* Also matches credential-bearing (`https://x-access-token:…@github.com/…`)
|
|
19
|
+
* and `ssh://git@github.com/…` forms.
|
|
20
|
+
*
|
|
21
|
+
* The repo group is lazy and the pattern is end-anchored so the optional
|
|
22
|
+
* `.git` strips a *trailing* suffix only — a greedy or dot-excluding group
|
|
23
|
+
* would truncate dotted names such as `paysdoc.nl` (issue #779).
|
|
24
|
+
*/
|
|
25
|
+
const HTTPS_REMOTE_RE = /github\.com\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/;
|
|
26
|
+
/** SCP-style SSH GitHub remote: `git@github.com:owner/repo[.git]`. */
|
|
27
|
+
const SSH_REMOTE_RE = /git@github\.com:([^/]+)\/([^/]+?)(?:\.git)?$/;
|
|
28
|
+
/**
|
|
29
|
+
* Parses a `RepoIdentifier` out of a GitHub remote URL (HTTPS or SSH).
|
|
30
|
+
* Returns null when the URL is not a parseable GitHub remote, leaving the
|
|
31
|
+
* error contract to each caller.
|
|
32
|
+
*
|
|
33
|
+
* Pure — the single source of truth for GitHub remote-URL parsing.
|
|
34
|
+
*/
|
|
35
|
+
export function parseGitHubRemoteUrl(remoteUrl) {
|
|
36
|
+
const url = remoteUrl.trim();
|
|
37
|
+
const match = url.match(HTTPS_REMOTE_RE) ?? url.match(SSH_REMOTE_RE);
|
|
38
|
+
if (!match)
|
|
39
|
+
return null;
|
|
40
|
+
return { owner: match[1], repo: match[2], platform: Platform.GitHub };
|
|
41
|
+
}
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// readLocalRepoInfo
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
/**
|
|
46
|
+
* Reads the local git remote URL (through the core's `readOriginRemoteUrl`)
|
|
47
|
+
* and parses owner/repo from it. Supports both HTTPS and SSH GitHub URL
|
|
48
|
+
* formats. Throws if the remote URL cannot be parsed.
|
|
49
|
+
*
|
|
50
|
+
* The try/catch spans BOTH the core read and the parse, so a non-GitHub
|
|
51
|
+
* remote's inner `Could not parse GitHub URL: …` message is still wrapped
|
|
52
|
+
* in the same outer `Failed to get repo info: …` a merged `@adw-779`
|
|
53
|
+
* scenario asserts on.
|
|
54
|
+
*/
|
|
55
|
+
export function readLocalRepoInfo(cwd) {
|
|
56
|
+
try {
|
|
57
|
+
const remoteUrl = readOriginRemoteUrl(cwd);
|
|
58
|
+
const info = parseGitHubRemoteUrl(remoteUrl);
|
|
59
|
+
if (!info) {
|
|
60
|
+
throw new Error(`Could not parse GitHub URL: ${remoteUrl}`);
|
|
61
|
+
}
|
|
62
|
+
return info;
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
throw new Error(`Failed to get repo info: ${error}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
// resolveBootstrapGitIdentity
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
/** The built-in default when nothing else resolves — deliberately forge-shaped, and deliberately not in the core (issue #793). */
|
|
72
|
+
export const ADW_BOT_FALLBACK_IDENTITY = {
|
|
73
|
+
authorName: 'ADW Bot',
|
|
74
|
+
authorEmail: 'adw-bot@users.noreply.github.com',
|
|
75
|
+
committerName: 'ADW Bot',
|
|
76
|
+
committerEmail: 'adw-bot@users.noreply.github.com',
|
|
77
|
+
};
|
|
78
|
+
/** Derives the GitHub App's bot identity from its id/slug. */
|
|
79
|
+
function deriveAppBotIdentity(appId, appSlug) {
|
|
80
|
+
const botName = `${appSlug}[bot]`;
|
|
81
|
+
const botEmail = `${appId}+${appSlug}[bot]@users.noreply.github.com`;
|
|
82
|
+
return { authorName: botName, authorEmail: botEmail, committerName: botName, committerEmail: botEmail };
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Resolves a complete git author/committer identity before a GitContext exists.
|
|
86
|
+
* Resolution order:
|
|
87
|
+
* 1. GitHub App bot identity (if App configured)
|
|
88
|
+
* 2. GIT_AUTHOR_* / GIT_COMMITTER_* env vars (the core's `readEnvGitIdentity`)
|
|
89
|
+
* 3. `git config user.name / user.email` (the core's `readGitConfigIdentity`)
|
|
90
|
+
* 4. Built-in ADW Bot default (never returns empty fields)
|
|
91
|
+
*
|
|
92
|
+
* Same exported name, same deps shape and defaults as the pre-#793 resolver
|
|
93
|
+
* this replaces, so every call site and every existing assertion survives
|
|
94
|
+
* unchanged.
|
|
95
|
+
*/
|
|
96
|
+
export function resolveBootstrapGitIdentity(deps = {}) {
|
|
97
|
+
const env = deps.env ?? process.env;
|
|
98
|
+
const isAppConfigured = deps.isAppConfigured ?? (() => Boolean(env['GITHUB_APP_ID'] && env['GITHUB_APP_SLUG'] && env['GITHUB_APP_PRIVATE_KEY_PATH']));
|
|
99
|
+
if (isAppConfigured()) {
|
|
100
|
+
const appId = env['GITHUB_APP_ID'];
|
|
101
|
+
const appSlug = env['GITHUB_APP_SLUG'];
|
|
102
|
+
if (appId && appSlug) {
|
|
103
|
+
return deriveAppBotIdentity(appId, appSlug);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return readEnvGitIdentity(env)
|
|
107
|
+
?? readGitConfigIdentity({ env, exec: deps.exec })
|
|
108
|
+
?? ADW_BOT_FALLBACK_IDENTITY;
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=githubIdentity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"githubIdentity.js","sourceRoot":"","sources":["../../../src/providers/github/githubIdentity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub implementation of the IssueTracker provider interface.
|
|
3
|
+
*
|
|
4
|
+
* Binds `createGhRepoApi(ctx)` once at construction, over a `GitContext` the
|
|
5
|
+
* caller already holds — the adapter constructs no context, resolves no
|
|
6
|
+
* token, and reads no environment. Every method reproduces the command,
|
|
7
|
+
* parse, error policy and log line of its absorbed legacy free function
|
|
8
|
+
* (`adws/github/issueApi.ts` / `issueListApi.ts` / `labelManager.ts` /
|
|
9
|
+
* `projectBoardApi.ts`) exactly, logging through the injected `Logger` port.
|
|
10
|
+
* The HITL Slack notification and the `adw:*` label catalogue are ADW
|
|
11
|
+
* behaviours re-homed as the optional `onStatusMoved`/`resolveLabelDefinition`
|
|
12
|
+
* seams — the library itself never learns about Slack or about ADW's colours.
|
|
13
|
+
*/
|
|
14
|
+
import { type GitContext, type Logger } from '../../git/index.js';
|
|
15
|
+
import type { IssueTracker, RepoIdentifier, Issue, IssueComment, IssueSummary, IssueListQuery, IssueListEntry } from '../types.js';
|
|
16
|
+
import { BoardStatus } from '../types.js';
|
|
17
|
+
/** A label's canonical presentation — name, colour, and description — for the `applyLabel` lazy-create path. */
|
|
18
|
+
export interface GitHubLabelDefinition {
|
|
19
|
+
readonly name: string;
|
|
20
|
+
readonly color: string;
|
|
21
|
+
readonly description: string;
|
|
22
|
+
}
|
|
23
|
+
export interface GitHubIssueTrackerDeps {
|
|
24
|
+
readonly logger?: Logger;
|
|
25
|
+
/**
|
|
26
|
+
* Invoked (and awaited) only after a move that returned `true`, inside the
|
|
27
|
+
* same try/catch as the move; a throw from it is logged as a failed move
|
|
28
|
+
* and yields `false`.
|
|
29
|
+
*/
|
|
30
|
+
readonly onStatusMoved?: (issueNumber: number, status: BoardStatus) => void | Promise<void>;
|
|
31
|
+
/** Consulted only on `applyLabel`'s lazy-create path; default `{ name: label, color: 'ededed', description: '' }`. */
|
|
32
|
+
readonly resolveLabelDefinition?: (label: string) => GitHubLabelDefinition;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* IssueTracker implementation for GitHub Issues, bound to a specific
|
|
36
|
+
* repository and `GitContext` at construction time.
|
|
37
|
+
*/
|
|
38
|
+
export declare class GitHubIssueTracker implements IssueTracker {
|
|
39
|
+
private readonly repoId;
|
|
40
|
+
private readonly gh;
|
|
41
|
+
private readonly logger;
|
|
42
|
+
private readonly onStatusMoved?;
|
|
43
|
+
private readonly resolveLabelDefinition;
|
|
44
|
+
constructor(ctx: GitContext, repoId: RepoIdentifier, deps?: GitHubIssueTrackerDeps);
|
|
45
|
+
fetchIssue(issueNumber: number): Promise<Issue>;
|
|
46
|
+
commentOnIssue(issueNumber: number, body: string): void;
|
|
47
|
+
deleteComment(commentId: string): void;
|
|
48
|
+
getIssueState(issueNumber: number): string;
|
|
49
|
+
closeIssue(issueNumber: number, comment?: string): Promise<boolean>;
|
|
50
|
+
fetchComments(issueNumber: number): IssueComment[];
|
|
51
|
+
moveToStatus(issueNumber: number, status: BoardStatus): Promise<boolean>;
|
|
52
|
+
fetchLabels(issueNumber: number): readonly string[];
|
|
53
|
+
addLabel(issueNumber: number, labelName: string): void;
|
|
54
|
+
applyLabel(issueNumber: number, labelName: string): void;
|
|
55
|
+
ensureLabel(name: string, color: string, description: string): void;
|
|
56
|
+
createIssue(title: string, body: string): number;
|
|
57
|
+
updateIssueBody(issueNumber: number, body: string): void;
|
|
58
|
+
searchOpenIssues(search: string, limit: number): readonly IssueSummary[];
|
|
59
|
+
findOpenUpgradeIssue(): number | null;
|
|
60
|
+
listIssues(query: IssueListQuery): readonly IssueListEntry[];
|
|
61
|
+
getIssueTitle(issueNumber: number): string;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Factory function to create a GitHub IssueTracker provider, bound to the
|
|
65
|
+
* given `GitContext` and repository. Refuses a context bound to a different
|
|
66
|
+
* owner/repo than `repoId`.
|
|
67
|
+
*/
|
|
68
|
+
export declare function createGitHubIssueTracker(ctx: GitContext, repoId: RepoIdentifier, deps?: GitHubIssueTrackerDeps): IssueTracker;
|
|
69
|
+
//# sourceMappingURL=githubIssueTracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"githubIssueTracker.d.ts","sourceRoot":"","sources":["../../../src/providers/github/githubIssueTracker.ts"],"names":[],"mappings":"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"}
|