@appliqation/pr-raise 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +72 -0
- package/dist/cli/audit.js +21 -0
- package/dist/cli/audit.js.map +1 -0
- package/dist/cli/index.js +76 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config/env.js +23 -0
- package/dist/config/env.js.map +1 -0
- package/dist/git/gitClient.js +88 -0
- package/dist/git/gitClient.js.map +1 -0
- package/dist/github/prClient.js +54 -0
- package/dist/github/prClient.js.map +1 -0
- package/dist/orchestrator/raise.js +38 -0
- package/dist/orchestrator/raise.js.map +1 -0
- package/package.json +37 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Appliqation Pty Ltd
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Appliqation PR-Raise
|
|
2
|
+
|
|
3
|
+
**Commits whatever's already changed in a local checkout, pushes, and opens (or reuses) a pull request.**
|
|
4
|
+
|
|
5
|
+
Fully mechanical — no LLM anywhere in this repo. Deciding *what* to change is someone else's job (a human, or a sibling agent like [`appliqation-scriptgen`](https://github.com/appliqation/appliqation-scriptgen) or [`appliqation-defect-fix`](https://github.com/appliqation/appliqation-defect-fix)); this repo's only job is turning an already-made change into a real, reviewable pull request, reliably and idempotently.
|
|
6
|
+
|
|
7
|
+
## Why a separate, dumb agent
|
|
8
|
+
|
|
9
|
+
Committing a known set of files and opening a PR needs no judgment — so it doesn't get one. Every other agent in this family stops at "write the files locally"; none of them touch git or GitHub. This is the one place that does, which keeps the blast radius of any single agent's mistake contained: a bad fix from `appliqation-defect-fix` produces a bad PR you can review and close, never a bad push nobody saw coming from inside a reasoning loop.
|
|
10
|
+
|
|
11
|
+
## How it works
|
|
12
|
+
|
|
13
|
+
```mermaid
|
|
14
|
+
flowchart LR
|
|
15
|
+
A[local checkout<br/>with uncommitted changes] --> B{anything to commit?}
|
|
16
|
+
B -- no --> C[report and stop<br/>no push, no GitHub call]
|
|
17
|
+
B -- yes --> D[fetch + checkout/create branch]
|
|
18
|
+
D --> E[git add -A + commit]
|
|
19
|
+
E --> F[push]
|
|
20
|
+
F --> G{open PR already<br/>exists for this branch?}
|
|
21
|
+
G -- yes --> H[update its body]
|
|
22
|
+
G -- no --> I[open a new PR]
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
- **Credentials are its own.** It never reads Appliqation's per-project GitHub PAT — it authenticates with its own `GITHUB_TOKEN`, kept entirely separate from appq's credential store by design.
|
|
26
|
+
- **Idempotent PR handling.** Re-running against a branch that already has an open PR updates that PR's body instead of opening a second one.
|
|
27
|
+
- **No-op is a real, reported outcome.** If there's nothing to commit, it says so and stops — it never pushes or touches GitHub for a no-op.
|
|
28
|
+
|
|
29
|
+
## Quick start
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install -g @appliqation/pr-raise
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Create a `.env` file (in whatever directory you'll run it from) with:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
APPQ_API_KEY=your-appliqation-api-key # read-only, repo lookup only
|
|
39
|
+
GITHUB_TOKEN=your-github-token # this agent's own, with repo write access
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
appliqation-pr-raise raise \
|
|
44
|
+
--project-id <id> \
|
|
45
|
+
--repo-path /path/to/your/checkout \
|
|
46
|
+
--branch-name my-branch \
|
|
47
|
+
--pr-title "My change"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`--project-id` resolves the target repo/branch via Appliqation's `get_project_settings` (location only — no credentials come from there). Add `--pr-body`/`--pr-body-file`, `--base-branch`, or `--commit-message` as needed; `--json` prints a structured result instead of the human summary.
|
|
51
|
+
|
|
52
|
+
## Configuration
|
|
53
|
+
|
|
54
|
+
Copy `.env.example` to `.env`. Requires `APPQ_API_KEY` (read-only) and `GITHUB_TOKEN` (this agent's own, with repo write access).
|
|
55
|
+
|
|
56
|
+
## Development
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
git clone https://github.com/appliqation/appliqation-pr-raise.git
|
|
60
|
+
cd appliqation-pr-raise
|
|
61
|
+
npm install
|
|
62
|
+
cp .env.example .env # fill in APPQ_API_KEY (read-only, repo lookup only) and GITHUB_TOKEN
|
|
63
|
+
npm run dev -- raise --project-id <id> --repo-path <path> --branch-name <name> --pr-title <title>
|
|
64
|
+
npm run typecheck
|
|
65
|
+
npm test
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
See `CLAUDE.md` for a map of this repo if you're working in it with an AI coding assistant.
|
|
69
|
+
|
|
70
|
+
## License
|
|
71
|
+
|
|
72
|
+
MIT — see [LICENSE](./LICENSE).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Extracted out of cli/index.ts so this is testable without triggering that
|
|
2
|
+
// file's top-level program.parseAsync(process.argv) side effect — same
|
|
3
|
+
// reasoning as appliqation-autotest's cli/resolvers.ts.
|
|
4
|
+
//
|
|
5
|
+
// No LLM in this repo at all — RecordRaiseRunArgs has no model/usage/turns/
|
|
6
|
+
// budgetExceeded (all absent on the underlying AuditRecord type, unlike
|
|
7
|
+
// every other agent in this family).
|
|
8
|
+
import { safeRecord } from '@appliqation/agent-core';
|
|
9
|
+
export async function recordRaiseRun(args) {
|
|
10
|
+
const { sink, startedAt, endedAt, projectId, repoPath, branchName, result } = args;
|
|
11
|
+
await safeRecord(sink, {
|
|
12
|
+
agent: 'appliqation-pr-raise',
|
|
13
|
+
subcommand: 'raise',
|
|
14
|
+
startedAt,
|
|
15
|
+
endedAt,
|
|
16
|
+
durationMillis: endedAt - startedAt,
|
|
17
|
+
exitCode: result ? 0 : 1,
|
|
18
|
+
outcome: result ? { projectId, repoPath, branchName, ...result } : { projectId, repoPath, branchName, error: true },
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/cli/audit.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,uEAAuE;AACvE,wDAAwD;AACxD,EAAE;AACF,4EAA4E;AAC5E,wEAAwE;AACxE,qCAAqC;AAErC,OAAO,EAAE,UAAU,EAAkB,MAAM,yBAAyB,CAAC;AAcrE,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAwB;IAC3D,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACnF,MAAM,UAAU,CAAC,IAAI,EAAE;QACrB,KAAK,EAAE,sBAAsB;QAC7B,UAAU,EAAE,OAAO;QACnB,SAAS;QACT,OAAO;QACP,cAAc,EAAE,OAAO,GAAG,SAAS;QACnC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxB,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE;KACpH,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// `raise`: commit whatever's already changed in a local checkout, push,
|
|
3
|
+
// and open (or reuse) a pull request. No LLM involved — this is a
|
|
4
|
+
// mechanical git+GitHub operation, reusable by any caller that's already
|
|
5
|
+
// made the file changes it wants raised (appliqation-scriptgen today, a
|
|
6
|
+
// future defect-fix agent later, or a human running this directly).
|
|
7
|
+
import { readFile } from 'node:fs/promises';
|
|
8
|
+
import { Command } from 'commander';
|
|
9
|
+
import { createMcpClient } from '@appliqation/agent-core';
|
|
10
|
+
import { config } from '../config/env.js';
|
|
11
|
+
import { raise } from '../orchestrator/raise.js';
|
|
12
|
+
import { recordRaiseRun } from './audit.js';
|
|
13
|
+
const program = new Command();
|
|
14
|
+
program
|
|
15
|
+
.name('appliqation-pr-raise')
|
|
16
|
+
.description('Commit local changes in a repo checkout and open/reuse a pull request for them.');
|
|
17
|
+
program
|
|
18
|
+
.command('raise')
|
|
19
|
+
.description("Resolves the project's GitHub repo/branch via appq's get_project_settings (no credentials come from " +
|
|
20
|
+
"appq — this agent's own GITHUB_TOKEN does the actual git/GitHub work), then in --repo-path: fetch, " +
|
|
21
|
+
'checkout/create --branch-name, `git add -A` + commit whatever is already changed there, push, and ' +
|
|
22
|
+
'open a PR — or update the existing open PR for that branch if one is already there, never opening ' +
|
|
23
|
+
"a second one. If there's nothing to commit, reports that plainly and does not push or touch GitHub at all.")
|
|
24
|
+
.requiredOption('--project-id <id>', 'Appliqation project ID — resolves the target GitHub repo/branch')
|
|
25
|
+
.requiredOption('--repo-path <path>', 'local checkout that already has the changes to raise')
|
|
26
|
+
.requiredOption('--branch-name <name>', 'branch to commit to and open the PR from')
|
|
27
|
+
.requiredOption('--pr-title <title>', 'pull request title')
|
|
28
|
+
.option('--pr-body <text>', 'pull request body', '')
|
|
29
|
+
.option('--pr-body-file <path>', 'read the PR body from a file instead of --pr-body')
|
|
30
|
+
.option('--base-branch <name>', "override the project's configured default branch")
|
|
31
|
+
.option('--commit-message <message>', 'defaults to --pr-title')
|
|
32
|
+
.option('--json', 'print a single structured JSON result instead of a human-readable summary')
|
|
33
|
+
.action(async (opts) => {
|
|
34
|
+
const client = createMcpClient({ origin: config.appqOrigin, apiKey: config.appqApiKey() });
|
|
35
|
+
const prBody = opts.prBodyFile ? await readFile(opts.prBodyFile, 'utf-8') : opts.prBody;
|
|
36
|
+
const projectId = Number(opts.projectId);
|
|
37
|
+
const startedAt = Date.now();
|
|
38
|
+
let result;
|
|
39
|
+
try {
|
|
40
|
+
result = await raise({
|
|
41
|
+
client,
|
|
42
|
+
projectId,
|
|
43
|
+
repoPath: opts.repoPath,
|
|
44
|
+
branchName: opts.branchName,
|
|
45
|
+
prTitle: opts.prTitle,
|
|
46
|
+
prBody,
|
|
47
|
+
baseBranchOverride: opts.baseBranch,
|
|
48
|
+
commitMessage: opts.commitMessage,
|
|
49
|
+
githubToken: config.githubToken(),
|
|
50
|
+
gitAuthorName: config.gitAuthorName,
|
|
51
|
+
gitAuthorEmail: config.gitAuthorEmail,
|
|
52
|
+
commandTimeoutMs: config.commandTimeoutMs,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
// Audit write happens whether the run succeeded or threw — see
|
|
57
|
+
// @appliqation/agent-core's audit/sink.ts: safeRecord() (used
|
|
58
|
+
// inside recordRaiseRun) never lets a failed/unreachable audit sink
|
|
59
|
+
// affect this process's real outcome.
|
|
60
|
+
await recordRaiseRun({ sink: config.auditSink, startedAt, endedAt: Date.now(), projectId, repoPath: opts.repoPath, branchName: opts.branchName, result });
|
|
61
|
+
}
|
|
62
|
+
if (opts.json) {
|
|
63
|
+
console.log(JSON.stringify(result, null, 2));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (!result.committed) {
|
|
67
|
+
console.log(result.skippedReason);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
console.log(`Committed and pushed to ${opts.branchName}.`);
|
|
71
|
+
if (result.pr) {
|
|
72
|
+
console.log(result.pr.created ? `Opened PR: ${result.pr.url}` : `Updated existing PR: ${result.pr.url}`);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
program.parseAsync(process.argv);
|
|
76
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import 'dotenv/config';
|
|
2
|
+
import { required, optional } from '@appliqation/agent-core/config';
|
|
3
|
+
import { resolveAuditSink } from '@appliqation/agent-core/audit';
|
|
4
|
+
export const config = {
|
|
5
|
+
appqOrigin: optional('APPQ_ORIGIN') ?? 'https://appq.appliqation.io',
|
|
6
|
+
appqApiKey: () => required('APPQ_API_KEY'),
|
|
7
|
+
// This agent's own GitHub token — deliberately NOT the per-project PAT
|
|
8
|
+
// appq stores (appq never hands that out to this client; it only ever
|
|
9
|
+
// returns repo_url/branch/tests_dir via get_project_settings, no
|
|
10
|
+
// credentials). The operator running this agent supplies their own.
|
|
11
|
+
githubToken: () => required('GITHUB_TOKEN'),
|
|
12
|
+
gitAuthorName: optional('GIT_AUTHOR_NAME') ?? 'Appliqation PR Agent',
|
|
13
|
+
gitAuthorEmail: optional('GIT_AUTHOR_EMAIL') ?? 'noreply@appliqation.io',
|
|
14
|
+
commandTimeoutMs: Number(optional('COMMAND_TIMEOUT_MS') ?? 2 * 60 * 1000),
|
|
15
|
+
// Observability, entirely opt-in — see @appliqation/agent-core's audit/sink.ts.
|
|
16
|
+
auditSink: resolveAuditSink({
|
|
17
|
+
auditMongoUri: optional('AUDIT_MONGO_URI'),
|
|
18
|
+
auditMongoDb: optional('AUDIT_MONGO_DB'),
|
|
19
|
+
auditMongoCollection: optional('AUDIT_MONGO_COLLECTION'),
|
|
20
|
+
auditJsonlPath: optional('AUDIT_JSONL_PATH'),
|
|
21
|
+
}),
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEjE,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,UAAU,EAAE,QAAQ,CAAC,aAAa,CAAC,IAAI,6BAA6B;IACpE,UAAU,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC;IAC1C,uEAAuE;IACvE,sEAAsE;IACtE,iEAAiE;IACjE,oEAAoE;IACpE,WAAW,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC;IAC3C,aAAa,EAAE,QAAQ,CAAC,iBAAiB,CAAC,IAAI,sBAAsB;IACpE,cAAc,EAAE,QAAQ,CAAC,kBAAkB,CAAC,IAAI,wBAAwB;IACxE,gBAAgB,EAAE,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;IAEzE,gFAAgF;IAChF,SAAS,EAAE,gBAAgB,CAAC;QAC1B,aAAa,EAAE,QAAQ,CAAC,iBAAiB,CAAC;QAC1C,YAAY,EAAE,QAAQ,CAAC,gBAAgB,CAAC;QACxC,oBAAoB,EAAE,QAAQ,CAAC,wBAAwB,CAAC;QACxD,cAAc,EAAE,QAAQ,CAAC,kBAAkB,CAAC;KAC7C,CAAC;CACH,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// A thin, real `git` CLI wrapper. No LLM is involved anywhere in this agent
|
|
2
|
+
// — committing and pushing a known set of local changes is fully mechanical,
|
|
3
|
+
// so there's no tool-calling loop, no allowlist-gated dispatch the way
|
|
4
|
+
// appliqation-scriptgen's shell surface needs (that one exists specifically
|
|
5
|
+
// because an LLM chooses what to run there; here, this code is the only
|
|
6
|
+
// thing that ever decides what git command runs).
|
|
7
|
+
import { execFile } from 'node:child_process';
|
|
8
|
+
// Same hand-rolled wrapper as appliqation-scriptgen's codingTools.ts, for
|
|
9
|
+
// the same reason: util.promisify(execFile) only resolves {stdout, stderr}
|
|
10
|
+
// via an internal Node symbol that a mocked module in tests won't carry.
|
|
11
|
+
function execFileAsync(command, args, options) {
|
|
12
|
+
return new Promise((resolvePromise, rejectPromise) => {
|
|
13
|
+
execFile(command, args, options, (error, stdout, stderr) => {
|
|
14
|
+
if (error) {
|
|
15
|
+
const failure = error;
|
|
16
|
+
failure.stdout = String(stdout ?? '');
|
|
17
|
+
failure.stderr = String(stderr ?? '');
|
|
18
|
+
rejectPromise(failure);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
resolvePromise({ stdout: String(stdout ?? ''), stderr: String(stderr ?? '') });
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
export class GitClient {
|
|
27
|
+
repoPath;
|
|
28
|
+
timeoutMs;
|
|
29
|
+
constructor(repoPath, timeoutMs) {
|
|
30
|
+
this.repoPath = repoPath;
|
|
31
|
+
this.timeoutMs = timeoutMs;
|
|
32
|
+
}
|
|
33
|
+
async git(args) {
|
|
34
|
+
return execFileAsync('git', args, { cwd: this.repoPath, timeout: this.timeoutMs, maxBuffer: 10 * 1024 * 1024 });
|
|
35
|
+
}
|
|
36
|
+
async statusPorcelain() {
|
|
37
|
+
return (await this.git(['status', '--porcelain'])).stdout;
|
|
38
|
+
}
|
|
39
|
+
async hasUncommittedChanges() {
|
|
40
|
+
return (await this.statusPorcelain()).trim().length > 0;
|
|
41
|
+
}
|
|
42
|
+
async fetch(remote = 'origin') {
|
|
43
|
+
await this.git(['fetch', remote]);
|
|
44
|
+
}
|
|
45
|
+
async localBranchExists(branchName) {
|
|
46
|
+
try {
|
|
47
|
+
await this.git(['rev-parse', '--verify', '--quiet', `refs/heads/${branchName}`]);
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** Checks out branchName, creating it from origin/baseBranch if it doesn't exist locally yet. Never force-resets an existing local branch. */
|
|
55
|
+
async checkoutBranch(branchName, baseBranch) {
|
|
56
|
+
if (await this.localBranchExists(branchName)) {
|
|
57
|
+
await this.git(['checkout', branchName]);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
await this.git(['checkout', '-b', branchName, `origin/${baseBranch}`]);
|
|
61
|
+
}
|
|
62
|
+
async addAll() {
|
|
63
|
+
await this.git(['add', '-A']);
|
|
64
|
+
}
|
|
65
|
+
/** Returns { committed: false } for "nothing to commit" rather than throwing — that's a legitimate outcome, not a failure. */
|
|
66
|
+
async commit(message, authorName, authorEmail) {
|
|
67
|
+
try {
|
|
68
|
+
await this.git(['-c', `user.name=${authorName}`, '-c', `user.email=${authorEmail}`, 'commit', '-m', message]);
|
|
69
|
+
return { committed: true };
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
const e = err;
|
|
73
|
+
if (/nothing to commit/i.test(e.stdout ?? ''))
|
|
74
|
+
return { committed: false };
|
|
75
|
+
throw err;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Pushes HEAD to branchName on remoteUrl, authenticating with token only
|
|
80
|
+
* for this one push — never persisted into .git/config, so the token
|
|
81
|
+
* doesn't linger in the checkout after this process exits.
|
|
82
|
+
*/
|
|
83
|
+
async pushWithToken(remoteUrl, token, branchName) {
|
|
84
|
+
const authedUrl = remoteUrl.replace('https://', `https://x-access-token:${token}@`);
|
|
85
|
+
await this.git(['push', authedUrl, `HEAD:refs/heads/${branchName}`]);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=gitClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitClient.js","sourceRoot":"","sources":["../../src/git/gitClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Idempotent PR open/reuse — mirrors workers/automan-worker's
|
|
2
|
+
// GitHubCommitClientAdapter.ensurePr() exactly (list open PRs for this
|
|
3
|
+
// head first, reuse if found; rebuild the body rather than append, so
|
|
4
|
+
// repeat calls stay accurate rather than accumulating stale text), the one
|
|
5
|
+
// proven pattern in this workspace for "don't open a second PR for a
|
|
6
|
+
// branch that already has one open".
|
|
7
|
+
import { Octokit } from '@octokit/rest';
|
|
8
|
+
/** Parses owner/repo from either https://github.com/owner/repo(.git) or git@github.com:owner/repo(.git). */
|
|
9
|
+
export function parseGitHubRepoUrl(url) {
|
|
10
|
+
const match = url.match(/github\.com[/:]([^/]+)\/([^/.]+?)(\.git)?\/?$/);
|
|
11
|
+
if (!match) {
|
|
12
|
+
throw new Error(`Could not parse a GitHub owner/repo out of repo_url "${url}"`);
|
|
13
|
+
}
|
|
14
|
+
return { owner: match[1], repo: match[2] };
|
|
15
|
+
}
|
|
16
|
+
export class PrClient {
|
|
17
|
+
octokit;
|
|
18
|
+
constructor(token) {
|
|
19
|
+
this.octokit = new Octokit({ auth: token });
|
|
20
|
+
}
|
|
21
|
+
async ensurePr(target, opts) {
|
|
22
|
+
const existing = await this.octokit.pulls.list({
|
|
23
|
+
owner: target.owner,
|
|
24
|
+
repo: target.repo,
|
|
25
|
+
head: `${target.owner}:${opts.head}`,
|
|
26
|
+
state: 'open',
|
|
27
|
+
});
|
|
28
|
+
if (existing.data.length > 0) {
|
|
29
|
+
const pr = existing.data[0];
|
|
30
|
+
await this.octokit.pulls.update({ owner: target.owner, repo: target.repo, pull_number: pr.number, body: opts.body });
|
|
31
|
+
return { number: pr.number, url: pr.html_url, created: false };
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
const created = await this.octokit.pulls.create({
|
|
35
|
+
owner: target.owner,
|
|
36
|
+
repo: target.repo,
|
|
37
|
+
head: opts.head,
|
|
38
|
+
base: opts.base,
|
|
39
|
+
title: opts.title,
|
|
40
|
+
body: opts.body,
|
|
41
|
+
});
|
|
42
|
+
return { number: created.data.number, url: created.data.html_url, created: true };
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
const e = err;
|
|
46
|
+
if (e.status === 422 && /No commits between/i.test(e.message ?? '')) {
|
|
47
|
+
throw new Error(`GitHub rejected the PR: no commits between "${opts.base}" and "${opts.head}" yet. ` +
|
|
48
|
+
'This can happen if the push hasn\'t landed yet — check the push actually succeeded.');
|
|
49
|
+
}
|
|
50
|
+
throw err;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=prClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prClient.js","sourceRoot":"","sources":["../../src/github/prClient.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,uEAAuE;AACvE,sEAAsE;AACtE,2EAA2E;AAC3E,qEAAqE;AACrE,qCAAqC;AAErC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAOxC,4GAA4G;AAC5G,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACzE,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,wDAAwD,GAAG,GAAG,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAC7C,CAAC;AAQD,MAAM,OAAO,QAAQ;IACF,OAAO,CAAU;IAElC,YAAY,KAAa;QACvB,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,MAAgB,EAAE,IAAiE;QAChG,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC;YAC7C,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,IAAI,EAAE,GAAG,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,EAAE;YACpC,KAAK,EAAE,MAAM;SACd,CAAC,CAAC;QAEH,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC5B,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YACrH,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACjE,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC;gBAC9C,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,IAAI,EAAE,IAAI,CAAC,IAAI;aAChB,CAAC,CAAC;YACH,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACpF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,GAAG,GAA4C,CAAC;YACvD,IAAI,CAAC,CAAC,MAAM,KAAK,GAAG,IAAI,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,CAAC;gBACpE,MAAM,IAAI,KAAK,CACb,+CAA+C,IAAI,CAAC,IAAI,UAAU,IAAI,CAAC,IAAI,SAAS;oBAClF,qFAAqF,CACxF,CAAC;YACJ,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Ties it together: resolve the target repo/branch via appq's existing
|
|
2
|
+
// get_project_settings (repo_url/branch/tests_dir only — no credentials;
|
|
3
|
+
// appq never hands out the per-project GitHub PAT to this client. This
|
|
4
|
+
// agent's own GitHub token, from its own .env, is what actually
|
|
5
|
+
// authenticates every git/GitHub call below), commit whatever's already
|
|
6
|
+
// changed in the given local checkout, push, and open or reuse a PR.
|
|
7
|
+
import { GitClient } from '../git/gitClient.js';
|
|
8
|
+
import { PrClient, parseGitHubRepoUrl } from '../github/prClient.js';
|
|
9
|
+
export async function raise(opts) {
|
|
10
|
+
const settingsResult = await opts.client.callTool('get_project_settings', { project_id: opts.projectId });
|
|
11
|
+
if (!settingsResult.ok) {
|
|
12
|
+
throw new Error(`get_project_settings failed for project ${opts.projectId}: ${settingsResult.text}`);
|
|
13
|
+
}
|
|
14
|
+
const settings = JSON.parse(settingsResult.text);
|
|
15
|
+
if (!settings.github_repo_url) {
|
|
16
|
+
throw new Error(`Project ${opts.projectId} has no GitHub repo configured (github_repo_url is empty).`);
|
|
17
|
+
}
|
|
18
|
+
const baseBranch = opts.baseBranchOverride ?? settings.github_branch ?? 'main';
|
|
19
|
+
const target = parseGitHubRepoUrl(settings.github_repo_url);
|
|
20
|
+
const git = new GitClient(opts.repoPath, opts.commandTimeoutMs);
|
|
21
|
+
await git.fetch();
|
|
22
|
+
await git.checkoutBranch(opts.branchName, baseBranch);
|
|
23
|
+
await git.addAll();
|
|
24
|
+
const { committed } = await git.commit(opts.commitMessage ?? opts.prTitle, opts.gitAuthorName, opts.gitAuthorEmail);
|
|
25
|
+
if (!committed) {
|
|
26
|
+
return {
|
|
27
|
+
committed: false,
|
|
28
|
+
pushed: false,
|
|
29
|
+
pr: null,
|
|
30
|
+
skippedReason: 'Nothing to commit — the working tree already matches HEAD.',
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
await git.pushWithToken(`https://github.com/${target.owner}/${target.repo}.git`, opts.githubToken, opts.branchName);
|
|
34
|
+
const prClient = new PrClient(opts.githubToken);
|
|
35
|
+
const pr = await prClient.ensurePr(target, { head: opts.branchName, base: baseBranch, title: opts.prTitle, body: opts.prBody });
|
|
36
|
+
return { committed: true, pushed: true, pr };
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=raise.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raise.js","sourceRoot":"","sources":["../../src/orchestrator/raise.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,yEAAyE;AACzE,uEAAuE;AACvE,gEAAgE;AAChE,wEAAwE;AACxE,qEAAqE;AAGrE,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AA8BrE,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,IAAkB;IAC5C,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;IAC1G,IAAI,CAAC,cAAc,CAAC,EAAE,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,2CAA2C,IAAI,CAAC,SAAS,KAAK,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC;IACvG,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAoB,CAAC;IACpE,IAAI,CAAC,QAAQ,CAAC,eAAe,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,CAAC,SAAS,4DAA4D,CAAC,CAAC;IACzG,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,CAAC,kBAAkB,IAAI,QAAQ,CAAC,aAAa,IAAI,MAAM,CAAC;IAC/E,MAAM,MAAM,GAAG,kBAAkB,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;IAE5D,MAAM,GAAG,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAChE,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;IAClB,MAAM,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IACtD,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;IAEpH,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,MAAM,EAAE,KAAK;YACb,EAAE,EAAE,IAAI;YACR,aAAa,EAAE,4DAA4D;SAC5E,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,CAAC,aAAa,CAAC,sBAAsB,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,IAAI,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IAEpH,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAChD,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAEhI,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;AAC/C,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@appliqation/pr-raise",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Standalone agent that commits local file changes in a repo checkout and opens (or reuses) a pull request. Fully mechanical \u2014 no LLM involved \u2014 reusable for scripts from appliqation-scriptgen or code changes from any future defect-fix agent.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"appliqation-pr-raise": "./dist/cli/index.js"
|
|
8
|
+
},
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": ">=20"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist/",
|
|
14
|
+
"README.md",
|
|
15
|
+
"LICENSE"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc -p tsconfig.build.json",
|
|
19
|
+
"dev": "tsx src/cli/index.ts",
|
|
20
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
21
|
+
"lint": "eslint src --ext .ts",
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"test:watch": "vitest"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@appliqation/agent-core": "^0.1.0",
|
|
27
|
+
"@octokit/rest": "^21.1.1",
|
|
28
|
+
"commander": "^13.1.0",
|
|
29
|
+
"dotenv": "^16.4.7"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/node": "^22.13.10",
|
|
33
|
+
"tsx": "^4.19.3",
|
|
34
|
+
"typescript": "^5.8.2",
|
|
35
|
+
"vitest": "^3.2.7"
|
|
36
|
+
}
|
|
37
|
+
}
|