@perrylink/dsh-github 0.6.2 → 0.6.4
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/README.es.md +1 -1
- package/README.hi.md +1 -1
- package/README.md +2 -1
- package/README.pt.md +1 -1
- package/README.zh.md +1 -1
- package/lib/approval-gate.d.ts +1 -1
- package/lib/ci/bot.d.ts +2 -2
- package/lib/ci/pipeline.d.ts +2 -2
- package/lib/ci/review-rules.d.ts +2 -2
- package/lib/ci/tool.d.ts +1 -1
- package/lib/client.js +342 -0
- package/lib/commands.d.ts +2 -2
- package/lib/credential.d.ts +1 -1
- package/lib/github.d.ts +1 -1
- package/lib/index.d.ts +25 -4
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +29 -1
- package/lib/index.js.map +1 -1
- package/lib/jobs.d.ts +2 -2
- package/lib/state.d.ts +6 -6
- package/lib/tools.d.ts +2 -2
- package/lib/types/client.d.ts +13 -0
- package/package.json +144 -121
- package/scripts/action-patch.mjs +152 -152
- package/scripts/action-post.mjs +61 -61
- package/scripts/check-endpoints.mjs +48 -0
- package/scripts/fix-dts.mjs +39 -0
- package/scripts/local-test.mjs +259 -259
- package/scripts/prepare.mjs +9 -0
- package/scripts/verify-artifacts.mjs +32 -0
- package/scripts/verify-self-contained.mjs +27 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser half of `@perrylink/dsh-github` — the GitHub token configuration
|
|
3
|
+
* card contributed to the "Plugins" settings section.
|
|
4
|
+
* @module @perrylink/dsh-github/client
|
|
5
|
+
*/
|
|
6
|
+
import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
|
|
7
|
+
/** Required services (cordis fiber inject). */
|
|
8
|
+
export declare const inject: string[];
|
|
9
|
+
/**
|
|
10
|
+
* Mount the GitHub configuration card into the plugins settings section.
|
|
11
|
+
* @param ctx - the browser plugin context.
|
|
12
|
+
*/
|
|
13
|
+
export declare function apply(ctx: ClientContext): void;
|
package/package.json
CHANGED
|
@@ -1,121 +1,144 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@perrylink/dsh-github",
|
|
3
|
-
"version": "0.6.
|
|
4
|
-
"description": "Official-grade GitHub CI for DeepSeek Harness: composite action (review PRs / fix CI / report), polling PR review bot with idempotent inline comments, a status-check gate, and approval-gated PR/issue/repo/file tools",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "lib/index.js",
|
|
7
|
-
"types": "lib/index.d.ts",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
"types": "./lib/index.d.ts",
|
|
11
|
-
"import": "./lib/index.js"
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
"
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
"
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
"
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
"
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
"
|
|
83
|
-
"
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
"
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
"
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
"
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
"
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
"
|
|
120
|
-
}
|
|
121
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@perrylink/dsh-github",
|
|
3
|
+
"version": "0.6.4",
|
|
4
|
+
"description": "Official-grade GitHub CI for DeepSeek Harness: composite action (review PRs / fix CI / report), polling PR review bot with idempotent inline comments, a status-check gate, and approval-gated PR/issue/repo/file tools",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"types": "lib/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/index.d.ts",
|
|
11
|
+
"import": "./lib/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./client": {
|
|
14
|
+
"types": "./lib/types/client.d.ts",
|
|
15
|
+
"default": "./lib/client.js"
|
|
16
|
+
},
|
|
17
|
+
"./package.json": "./package.json"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"lib",
|
|
21
|
+
"action.yml",
|
|
22
|
+
"scripts",
|
|
23
|
+
"cordis.patch.yml",
|
|
24
|
+
"README.md",
|
|
25
|
+
"README.zh.md",
|
|
26
|
+
"README.es.md",
|
|
27
|
+
"README.pt.md",
|
|
28
|
+
"README.hi.md",
|
|
29
|
+
"LICENSE"
|
|
30
|
+
],
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsc --noEmitOnError && node scripts/fix-dts.mjs",
|
|
33
|
+
"prepare": "node scripts/prepare.mjs",
|
|
34
|
+
"prepublishOnly": "npm run build && npm test",
|
|
35
|
+
"test": "vitest run",
|
|
36
|
+
"test:coverage": "vitest run --coverage",
|
|
37
|
+
"typecheck": "tsc --noEmit",
|
|
38
|
+
"lint": "oxlint",
|
|
39
|
+
"check:readmes": "node scripts/check-readmes.mjs",
|
|
40
|
+
"verify:self-contained": "node scripts/verify-self-contained.mjs",
|
|
41
|
+
"verify:artifacts": "node scripts/verify-artifacts.mjs"
|
|
42
|
+
},
|
|
43
|
+
"keywords": [
|
|
44
|
+
"dsh",
|
|
45
|
+
"dsh-plugin",
|
|
46
|
+
"deepseek-harness",
|
|
47
|
+
"github",
|
|
48
|
+
"github-actions",
|
|
49
|
+
"pull-request",
|
|
50
|
+
"code-review",
|
|
51
|
+
"ci",
|
|
52
|
+
"issue-tracker"
|
|
53
|
+
],
|
|
54
|
+
"license": "Apache-2.0",
|
|
55
|
+
"publishConfig": {
|
|
56
|
+
"access": "public"
|
|
57
|
+
},
|
|
58
|
+
"repository": {
|
|
59
|
+
"type": "git",
|
|
60
|
+
"url": "https://github.com/PerryLink/dsh-github"
|
|
61
|
+
},
|
|
62
|
+
"engines": {
|
|
63
|
+
"node": "^22.19.0 || >=24.0.0"
|
|
64
|
+
},
|
|
65
|
+
"dsh": {
|
|
66
|
+
"bundle": {
|
|
67
|
+
"patch": "./cordis.patch.yml"
|
|
68
|
+
},
|
|
69
|
+
"client": {
|
|
70
|
+
"inject": [
|
|
71
|
+
"@deepseek-ai/dsh-client-connection",
|
|
72
|
+
"@deepseek-ai/dsh-client-locale",
|
|
73
|
+
"@deepseek-ai/dsh-client-runtime",
|
|
74
|
+
"@deepseek-ai/dsh-client-ui-slots"
|
|
75
|
+
],
|
|
76
|
+
"platform": "web"
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
"dshWorkshop": {
|
|
80
|
+
"schema": "omdsh-workshop-package/v1",
|
|
81
|
+
"type": "plugin",
|
|
82
|
+
"integration": {
|
|
83
|
+
"protocol": "harness-profile",
|
|
84
|
+
"artifact": "cordis.patch.yml"
|
|
85
|
+
},
|
|
86
|
+
"install": {
|
|
87
|
+
"mode": "transactional",
|
|
88
|
+
"adapter": "profile-bundle",
|
|
89
|
+
"failurePolicy": "generation-rollback",
|
|
90
|
+
"touchesCurrentBeforeActivation": false
|
|
91
|
+
},
|
|
92
|
+
"lifecycle": {
|
|
93
|
+
"activation": "restart-profile",
|
|
94
|
+
"dispose": "supported"
|
|
95
|
+
},
|
|
96
|
+
"permissions": [
|
|
97
|
+
"network:outbound",
|
|
98
|
+
"filesystem:write"
|
|
99
|
+
],
|
|
100
|
+
"compatibility": {
|
|
101
|
+
"dshVersions": [
|
|
102
|
+
"0.1.1-rc.2"
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
"capability": {
|
|
106
|
+
"id": "gh-ci",
|
|
107
|
+
"kind": "command",
|
|
108
|
+
"invocation": "/ci",
|
|
109
|
+
"expected": "runs the review engine for the requested PR, posts idempotent inline review comments and publishes the status-check verdict (success / changes needed)"
|
|
110
|
+
},
|
|
111
|
+
"evidence": {
|
|
112
|
+
"install": null,
|
|
113
|
+
"failureIsolation": null,
|
|
114
|
+
"hotReload": null,
|
|
115
|
+
"remove": null
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"dependencies": {
|
|
119
|
+
"@deepseek-ai/schemastery": "^3.18.1"
|
|
120
|
+
},
|
|
121
|
+
"peerDependencies": {
|
|
122
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
123
|
+
"@deepseek-ai/dsh-credentials": ">=0.1.0-rc.8 <0.2.0",
|
|
124
|
+
"@deepseek-ai/dsh-llm": ">=0.1.0-rc.8 <0.2.0",
|
|
125
|
+
"@deepseek-ai/dsh-session": ">=0.1.0-rc.8 <0.2.0",
|
|
126
|
+
"@deepseek-ai/dsh-settings": ">=0.1.0-rc.8 <0.2.0",
|
|
127
|
+
"@deepseek-ai/dsh-tools": ">=0.1.0-rc.8 <0.2.0"
|
|
128
|
+
},
|
|
129
|
+
"devDependencies": {
|
|
130
|
+
"@deepseek-ai/cordis": "4.0.1",
|
|
131
|
+
"@deepseek-ai/cordis-plugin-loader": "1.0.2",
|
|
132
|
+
"@deepseek-ai/dsh-credentials": "0.1.1-rc.2",
|
|
133
|
+
"@deepseek-ai/dsh-llm": "0.1.1-rc.2",
|
|
134
|
+
"@deepseek-ai/dsh-session": "0.1.1-rc.2",
|
|
135
|
+
"@deepseek-ai/dsh-settings": "0.1.1-rc.2",
|
|
136
|
+
"@deepseek-ai/dsh-tools": "0.1.1-rc.2",
|
|
137
|
+
"@deepseek-ai/schemastery": "3.18.1",
|
|
138
|
+
"@types/node": "^22.0.0",
|
|
139
|
+
"@vitest/coverage-v8": "3.2.0",
|
|
140
|
+
"oxlint": "0.18.1",
|
|
141
|
+
"typescript": "^5.7.0",
|
|
142
|
+
"vitest": "^3.2.0"
|
|
143
|
+
}
|
|
144
|
+
}
|
package/scripts/action-patch.mjs
CHANGED
|
@@ -1,152 +1,152 @@
|
|
|
1
|
-
// Generates the dsh headless profile overlay and the task text for the
|
|
2
|
-
// composite action. Zero-dependency Node: every input arrives through the
|
|
3
|
-
// runner's INPUT_* environment variables (composite-action inputs), and every
|
|
4
|
-
// value is emitted as a JSON string (a valid YAML scalar) so arbitrary user
|
|
5
|
-
// input can never break the YAML structure.
|
|
6
|
-
//
|
|
7
|
-
// Writes to $INPUT_OUTPUT_DIR:
|
|
8
|
-
// dsh-github-ci.cordis.yml — the --patch overlay (Minimal persona + role
|
|
9
|
-
// line, model selection, sandbox, the minimal bash/editor toolset, and
|
|
10
|
-
// the dsh-github row with the full ci.* configuration).
|
|
11
|
-
// task.txt — the headless task for the selected mode.
|
|
12
|
-
import { mkdirSync, writeFileSync } from 'node:fs'
|
|
13
|
-
import { join } from 'node:path'
|
|
14
|
-
|
|
15
|
-
// Local-machine protection: the composite action resolves every path from the
|
|
16
|
-
// runner environment (RUNNER_TEMP for the output directory, GITHUB_WORKSPACE
|
|
17
|
-
// for the sandbox root). Outside a GitHub Actions runner those variables do
|
|
18
|
-
// not exist, and every fallback would silently write the profile overlay and
|
|
19
|
-
// task into the current working directory while a locally spawned `dsh`
|
|
20
|
-
// inherits the developer's real DSH_HOME. Refuse to run instead of guessing.
|
|
21
|
-
const runnerTemp = (process.env.RUNNER_TEMP ?? '').trim()
|
|
22
|
-
const workspace = (process.env.GITHUB_WORKSPACE ?? '').trim()
|
|
23
|
-
if (runnerTemp === '' || workspace === '') {
|
|
24
|
-
console.error('dsh-github: refusing to run outside a GitHub Actions runner — both RUNNER_TEMP and GITHUB_WORKSPACE must be set.')
|
|
25
|
-
console.error('dsh-github: to exercise the action locally, use `node scripts/local-test.mjs`; it pins DSH_HOME, DSH_PROFILE_DIR, and the output directory under the system temp directory.')
|
|
26
|
-
process.exit(1)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const env = (name) => process.env[name] ?? ''
|
|
30
|
-
const boolOf = (value, fallback) => value.trim() === '' ? fallback : value.trim() === 'true' || value.trim() === '1'
|
|
31
|
-
const listOf = (value) => value.split(',').map(item => item.trim()).filter(item => item.length > 0)
|
|
32
|
-
const y = (value) => JSON.stringify(value)
|
|
33
|
-
|
|
34
|
-
const task = env('INPUT_TASK').trim() || 'review'
|
|
35
|
-
const pr = env('INPUT_PR').trim()
|
|
36
|
-
const ownerRepo = env('INPUT_OWNER_REPO').trim()
|
|
37
|
-
const model = env('INPUT_MODEL').trim() || 'deepseek-v4-flash'
|
|
38
|
-
const engine = env('INPUT_ENGINE').trim() === 'model' ? 'model' : 'static'
|
|
39
|
-
const checkName = env('INPUT_CHECK_NAME').trim() || 'dsh-github-review'
|
|
40
|
-
const blocking = boolOf(env('INPUT_BLOCKING'), true)
|
|
41
|
-
const failOn = env('INPUT_FAIL_ON').trim() === 'warning' ? 'warning' : 'error'
|
|
42
|
-
const labelFilters = listOf(env('INPUT_LABEL_FILTERS'))
|
|
43
|
-
const pathFilters = listOf(env('INPUT_PATH_FILTERS'))
|
|
44
|
-
const maxDiffChars = Number(env('INPUT_MAX_DIFF_CHARS')) > 0 ? Math.floor(Number(env('INPUT_MAX_DIFF_CHARS'))) : 8000
|
|
45
|
-
const postComments = boolOf(env('INPUT_POST_COMMENTS'), true)
|
|
46
|
-
const postCheck = boolOf(env('INPUT_POST_CHECK'), true)
|
|
47
|
-
const requestTimeoutMs = Number(env('INPUT_REQUEST_TIMEOUT_MS')) > 0 ? Math.floor(Number(env('INPUT_REQUEST_TIMEOUT_MS'))) : 30000
|
|
48
|
-
const outputDir = env('INPUT_OUTPUT_DIR').trim() || join(process.env.RUNNER_TEMP ?? '.', 'dsh-github')
|
|
49
|
-
const customTask = env('INPUT_TASK_PROMPT').trim()
|
|
50
|
-
|
|
51
|
-
if ((task === 'review' || task === 'fix-ci') && pr === '') {
|
|
52
|
-
console.error('dsh-github: the `pr` input is required for the review and fix-ci tasks (defaults to github.event.pull_request.number on pull_request events)')
|
|
53
|
-
process.exit(1)
|
|
54
|
-
}
|
|
55
|
-
if (ownerRepo === '') {
|
|
56
|
-
console.error('dsh-github: the `owner-repo` input is required (defaults to github.repository)')
|
|
57
|
-
process.exit(1)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
mkdirSync(outputDir, { recursive: true })
|
|
61
|
-
|
|
62
|
-
const callJson = (extra) => JSON.stringify({ task: extra.task, pr, ownerRepo, ...extra })
|
|
63
|
-
|
|
64
|
-
let taskText
|
|
65
|
-
if (customTask !== '') {
|
|
66
|
-
taskText = customTask
|
|
67
|
-
} else if (task === 'review' && engine === 'static') {
|
|
68
|
-
taskText = `You are the dsh-github CI reviewer for this repository. Call the ci_run tool once with ${callJson({ task: 'review' })} and then reply with only the verdict and the summary line from its result.`
|
|
69
|
-
} else if (task === 'review') {
|
|
70
|
-
taskText = `You are a careful software engineer reviewing a GitHub pull request. First call ci_run with ${callJson({ task: 'analyze' })}. Review the diff yourself: correctness, security, style, and maintainability. Then call ci_run with ${callJson({ task: 'publish' })} plus a "body" holding your review (Markdown, verdict first, findings grouped by file) and a "findings" array for line-anchored problems you found. Finish by replying with only the verdict and the summary line from the publish result.`
|
|
71
|
-
} else if (task === 'fix-ci') {
|
|
72
|
-
taskText = `You are the dsh-github CI engineer for this repository. Investigate the CI failures of PR #${pr} in ${ownerRepo}: read the failing checks with gh_review (fields "ci"), inspect the code with gh_file and gh_repo, and use the bash tool only to read logs or run read-only diagnostics. Do NOT modify files. Write a fix plan as your final answer and call ci_run with ${callJson({ task: 'publish' })} plus a "body" holding that plan so it is posted as a review comment.`
|
|
73
|
-
} else {
|
|
74
|
-
taskText = `You are the dsh-github CI reporter for this repository. Generate a concise, factual report about ${ownerRepo}${pr !== '' ? ` PR #${pr}` : ''} using the read tools (gh_repo, gh_file, gh_review, gh_search). Write the report as your final answer and, if a pull request is being analyzed, call ci_run with ${callJson({ task: 'publish' })} plus a "body" holding the report so it is posted as a review comment.`
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const personaText = 'You are a helpful software engineer assistant.\nYou are the dsh-github CI assistant for this repository.'
|
|
78
|
-
|
|
79
|
-
const overlay = `# dsh-github CI overlay — generated by the composite action; every value is
|
|
80
|
-
# emitted by scripts/action-patch.mjs from the action inputs. Do not edit.
|
|
81
|
-
# Rows that already exist in dsh-base are replaced by id; new rows ride an
|
|
82
|
-
# insert block (non-insert patches only replace existing rows).
|
|
83
|
-
- id: persona
|
|
84
|
-
name: '@deepseek-ai/dsh-persona'
|
|
85
|
-
config:
|
|
86
|
-
text: ${y(personaText)}
|
|
87
|
-
complete: true
|
|
88
|
-
includeRuntimeContext: false
|
|
89
|
-
|
|
90
|
-
- id: agent-default-model
|
|
91
|
-
name: '@deepseek-ai/dsh-agent-default-model'
|
|
92
|
-
config:
|
|
93
|
-
provider: deepseek-official
|
|
94
|
-
model: ${y(model)}
|
|
95
|
-
|
|
96
|
-
- id: llm-deepseek
|
|
97
|
-
name: '@deepseek-ai/dsh-llm-deepseek'
|
|
98
|
-
config:
|
|
99
|
-
apiKeyEnv: DEEPSEEK_API_KEY
|
|
100
|
-
|
|
101
|
-
- id: sandbox-policy
|
|
102
|
-
name: '@deepseek-ai/dsh-sandbox-policy'
|
|
103
|
-
config:
|
|
104
|
-
mode: workspace-write
|
|
105
|
-
workspaceRoot: !!js process.env.GITHUB_WORKSPACE ?? process.cwd()
|
|
106
|
-
|
|
107
|
-
# The minimal toolset (persistent bash + editor), matching the official
|
|
108
|
-
# minimal preset: enough to investigate CI failures and generate reports,
|
|
109
|
-
# bounded by the workspace-write sandbox above.
|
|
110
|
-
- insert:
|
|
111
|
-
- id: terminal
|
|
112
|
-
name: '@deepseek-ai/dsh-terminal'
|
|
113
|
-
|
|
114
|
-
- id: terminal-bash
|
|
115
|
-
name: '@deepseek-ai/dsh-terminal-bash'
|
|
116
|
-
config:
|
|
117
|
-
timeoutMs: 300000
|
|
118
|
-
|
|
119
|
-
- id: persistent-bash
|
|
120
|
-
name: '@deepseek-ai/dsh-tool-bash-persistent'
|
|
121
|
-
config:
|
|
122
|
-
timeoutMs: 300000
|
|
123
|
-
|
|
124
|
-
- id: str-replace-editor
|
|
125
|
-
name: '@deepseek-ai/dsh-tool-str-replace-editor'
|
|
126
|
-
config:
|
|
127
|
-
maxOutputChars: 16000
|
|
128
|
-
|
|
129
|
-
- id: dsh-github
|
|
130
|
-
name: '@perrylink/dsh-github'
|
|
131
|
-
config:
|
|
132
|
-
tokenSource: env
|
|
133
|
-
tokenRef: DSH_GITHUB_TOKEN
|
|
134
|
-
maxDiffChars: ${maxDiffChars}
|
|
135
|
-
requestTimeoutMs: ${requestTimeoutMs}
|
|
136
|
-
ci:
|
|
137
|
-
enabled: true
|
|
138
|
-
engine: ${y(engine)}
|
|
139
|
-
autoApprove: ['ci.run']
|
|
140
|
-
checkName: ${y(checkName)}
|
|
141
|
-
blocking: ${blocking}
|
|
142
|
-
failOn: ${y(failOn)}
|
|
143
|
-
pollIntervalMs: 0
|
|
144
|
-
labelFilters: ${y(labelFilters)}
|
|
145
|
-
pathFilters: ${y(pathFilters)}
|
|
146
|
-
postComments: ${postComments}
|
|
147
|
-
reportDir: ${y(outputDir)}
|
|
148
|
-
`
|
|
149
|
-
|
|
150
|
-
writeFileSync(join(outputDir, 'dsh-github-ci.cordis.yml'), overlay)
|
|
151
|
-
writeFileSync(join(outputDir, 'task.txt'), taskText + '\n')
|
|
152
|
-
console.log(`dsh-github: overlay and task written to ${outputDir} (task: ${task}, engine: ${engine})`)
|
|
1
|
+
// Generates the dsh headless profile overlay and the task text for the
|
|
2
|
+
// composite action. Zero-dependency Node: every input arrives through the
|
|
3
|
+
// runner's INPUT_* environment variables (composite-action inputs), and every
|
|
4
|
+
// value is emitted as a JSON string (a valid YAML scalar) so arbitrary user
|
|
5
|
+
// input can never break the YAML structure.
|
|
6
|
+
//
|
|
7
|
+
// Writes to $INPUT_OUTPUT_DIR:
|
|
8
|
+
// dsh-github-ci.cordis.yml — the --patch overlay (Minimal persona + role
|
|
9
|
+
// line, model selection, sandbox, the minimal bash/editor toolset, and
|
|
10
|
+
// the dsh-github row with the full ci.* configuration).
|
|
11
|
+
// task.txt — the headless task for the selected mode.
|
|
12
|
+
import { mkdirSync, writeFileSync } from 'node:fs'
|
|
13
|
+
import { join } from 'node:path'
|
|
14
|
+
|
|
15
|
+
// Local-machine protection: the composite action resolves every path from the
|
|
16
|
+
// runner environment (RUNNER_TEMP for the output directory, GITHUB_WORKSPACE
|
|
17
|
+
// for the sandbox root). Outside a GitHub Actions runner those variables do
|
|
18
|
+
// not exist, and every fallback would silently write the profile overlay and
|
|
19
|
+
// task into the current working directory while a locally spawned `dsh`
|
|
20
|
+
// inherits the developer's real DSH_HOME. Refuse to run instead of guessing.
|
|
21
|
+
const runnerTemp = (process.env.RUNNER_TEMP ?? '').trim()
|
|
22
|
+
const workspace = (process.env.GITHUB_WORKSPACE ?? '').trim()
|
|
23
|
+
if (runnerTemp === '' || workspace === '') {
|
|
24
|
+
console.error('dsh-github: refusing to run outside a GitHub Actions runner — both RUNNER_TEMP and GITHUB_WORKSPACE must be set.')
|
|
25
|
+
console.error('dsh-github: to exercise the action locally, use `node scripts/local-test.mjs`; it pins DSH_HOME, DSH_PROFILE_DIR, and the output directory under the system temp directory.')
|
|
26
|
+
process.exit(1)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const env = (name) => process.env[name] ?? ''
|
|
30
|
+
const boolOf = (value, fallback) => value.trim() === '' ? fallback : value.trim() === 'true' || value.trim() === '1'
|
|
31
|
+
const listOf = (value) => value.split(',').map(item => item.trim()).filter(item => item.length > 0)
|
|
32
|
+
const y = (value) => JSON.stringify(value)
|
|
33
|
+
|
|
34
|
+
const task = env('INPUT_TASK').trim() || 'review'
|
|
35
|
+
const pr = env('INPUT_PR').trim()
|
|
36
|
+
const ownerRepo = env('INPUT_OWNER_REPO').trim()
|
|
37
|
+
const model = env('INPUT_MODEL').trim() || 'deepseek-v4-flash'
|
|
38
|
+
const engine = env('INPUT_ENGINE').trim() === 'model' ? 'model' : 'static'
|
|
39
|
+
const checkName = env('INPUT_CHECK_NAME').trim() || 'dsh-github-review'
|
|
40
|
+
const blocking = boolOf(env('INPUT_BLOCKING'), true)
|
|
41
|
+
const failOn = env('INPUT_FAIL_ON').trim() === 'warning' ? 'warning' : 'error'
|
|
42
|
+
const labelFilters = listOf(env('INPUT_LABEL_FILTERS'))
|
|
43
|
+
const pathFilters = listOf(env('INPUT_PATH_FILTERS'))
|
|
44
|
+
const maxDiffChars = Number(env('INPUT_MAX_DIFF_CHARS')) > 0 ? Math.floor(Number(env('INPUT_MAX_DIFF_CHARS'))) : 8000
|
|
45
|
+
const postComments = boolOf(env('INPUT_POST_COMMENTS'), true)
|
|
46
|
+
const postCheck = boolOf(env('INPUT_POST_CHECK'), true)
|
|
47
|
+
const requestTimeoutMs = Number(env('INPUT_REQUEST_TIMEOUT_MS')) > 0 ? Math.floor(Number(env('INPUT_REQUEST_TIMEOUT_MS'))) : 30000
|
|
48
|
+
const outputDir = env('INPUT_OUTPUT_DIR').trim() || join(process.env.RUNNER_TEMP ?? '.', 'dsh-github')
|
|
49
|
+
const customTask = env('INPUT_TASK_PROMPT').trim()
|
|
50
|
+
|
|
51
|
+
if ((task === 'review' || task === 'fix-ci') && pr === '') {
|
|
52
|
+
console.error('dsh-github: the `pr` input is required for the review and fix-ci tasks (defaults to github.event.pull_request.number on pull_request events)')
|
|
53
|
+
process.exit(1)
|
|
54
|
+
}
|
|
55
|
+
if (ownerRepo === '') {
|
|
56
|
+
console.error('dsh-github: the `owner-repo` input is required (defaults to github.repository)')
|
|
57
|
+
process.exit(1)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
mkdirSync(outputDir, { recursive: true })
|
|
61
|
+
|
|
62
|
+
const callJson = (extra) => JSON.stringify({ task: extra.task, pr, ownerRepo, ...extra })
|
|
63
|
+
|
|
64
|
+
let taskText
|
|
65
|
+
if (customTask !== '') {
|
|
66
|
+
taskText = customTask
|
|
67
|
+
} else if (task === 'review' && engine === 'static') {
|
|
68
|
+
taskText = `You are the dsh-github CI reviewer for this repository. Call the ci_run tool once with ${callJson({ task: 'review' })} and then reply with only the verdict and the summary line from its result.`
|
|
69
|
+
} else if (task === 'review') {
|
|
70
|
+
taskText = `You are a careful software engineer reviewing a GitHub pull request. First call ci_run with ${callJson({ task: 'analyze' })}. Review the diff yourself: correctness, security, style, and maintainability. Then call ci_run with ${callJson({ task: 'publish' })} plus a "body" holding your review (Markdown, verdict first, findings grouped by file) and a "findings" array for line-anchored problems you found. Finish by replying with only the verdict and the summary line from the publish result.`
|
|
71
|
+
} else if (task === 'fix-ci') {
|
|
72
|
+
taskText = `You are the dsh-github CI engineer for this repository. Investigate the CI failures of PR #${pr} in ${ownerRepo}: read the failing checks with gh_review (fields "ci"), inspect the code with gh_file and gh_repo, and use the bash tool only to read logs or run read-only diagnostics. Do NOT modify files. Write a fix plan as your final answer and call ci_run with ${callJson({ task: 'publish' })} plus a "body" holding that plan so it is posted as a review comment.`
|
|
73
|
+
} else {
|
|
74
|
+
taskText = `You are the dsh-github CI reporter for this repository. Generate a concise, factual report about ${ownerRepo}${pr !== '' ? ` PR #${pr}` : ''} using the read tools (gh_repo, gh_file, gh_review, gh_search). Write the report as your final answer and, if a pull request is being analyzed, call ci_run with ${callJson({ task: 'publish' })} plus a "body" holding the report so it is posted as a review comment.`
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const personaText = 'You are a helpful software engineer assistant.\nYou are the dsh-github CI assistant for this repository.'
|
|
78
|
+
|
|
79
|
+
const overlay = `# dsh-github CI overlay — generated by the composite action; every value is
|
|
80
|
+
# emitted by scripts/action-patch.mjs from the action inputs. Do not edit.
|
|
81
|
+
# Rows that already exist in dsh-base are replaced by id; new rows ride an
|
|
82
|
+
# insert block (non-insert patches only replace existing rows).
|
|
83
|
+
- id: persona
|
|
84
|
+
name: '@deepseek-ai/dsh-persona'
|
|
85
|
+
config:
|
|
86
|
+
text: ${y(personaText)}
|
|
87
|
+
complete: true
|
|
88
|
+
includeRuntimeContext: false
|
|
89
|
+
|
|
90
|
+
- id: agent-default-model
|
|
91
|
+
name: '@deepseek-ai/dsh-agent-default-model'
|
|
92
|
+
config:
|
|
93
|
+
provider: deepseek-official
|
|
94
|
+
model: ${y(model)}
|
|
95
|
+
|
|
96
|
+
- id: llm-deepseek
|
|
97
|
+
name: '@deepseek-ai/dsh-llm-deepseek'
|
|
98
|
+
config:
|
|
99
|
+
apiKeyEnv: DEEPSEEK_API_KEY
|
|
100
|
+
|
|
101
|
+
- id: sandbox-policy
|
|
102
|
+
name: '@deepseek-ai/dsh-sandbox-policy'
|
|
103
|
+
config:
|
|
104
|
+
mode: workspace-write
|
|
105
|
+
workspaceRoot: !!js process.env.GITHUB_WORKSPACE ?? process.cwd()
|
|
106
|
+
|
|
107
|
+
# The minimal toolset (persistent bash + editor), matching the official
|
|
108
|
+
# minimal preset: enough to investigate CI failures and generate reports,
|
|
109
|
+
# bounded by the workspace-write sandbox above.
|
|
110
|
+
- insert:
|
|
111
|
+
- id: terminal
|
|
112
|
+
name: '@deepseek-ai/dsh-terminal'
|
|
113
|
+
|
|
114
|
+
- id: terminal-bash
|
|
115
|
+
name: '@deepseek-ai/dsh-terminal-bash'
|
|
116
|
+
config:
|
|
117
|
+
timeoutMs: 300000
|
|
118
|
+
|
|
119
|
+
- id: persistent-bash
|
|
120
|
+
name: '@deepseek-ai/dsh-tool-bash-persistent'
|
|
121
|
+
config:
|
|
122
|
+
timeoutMs: 300000
|
|
123
|
+
|
|
124
|
+
- id: str-replace-editor
|
|
125
|
+
name: '@deepseek-ai/dsh-tool-str-replace-editor'
|
|
126
|
+
config:
|
|
127
|
+
maxOutputChars: 16000
|
|
128
|
+
|
|
129
|
+
- id: dsh-github
|
|
130
|
+
name: '@perrylink/dsh-github'
|
|
131
|
+
config:
|
|
132
|
+
tokenSource: env
|
|
133
|
+
tokenRef: DSH_GITHUB_TOKEN
|
|
134
|
+
maxDiffChars: ${maxDiffChars}
|
|
135
|
+
requestTimeoutMs: ${requestTimeoutMs}
|
|
136
|
+
ci:
|
|
137
|
+
enabled: true
|
|
138
|
+
engine: ${y(engine)}
|
|
139
|
+
autoApprove: ['ci.run']
|
|
140
|
+
checkName: ${y(checkName)}
|
|
141
|
+
blocking: ${blocking}
|
|
142
|
+
failOn: ${y(failOn)}
|
|
143
|
+
pollIntervalMs: 0
|
|
144
|
+
labelFilters: ${y(labelFilters)}
|
|
145
|
+
pathFilters: ${y(pathFilters)}
|
|
146
|
+
postComments: ${postComments}
|
|
147
|
+
reportDir: ${y(outputDir)}
|
|
148
|
+
`
|
|
149
|
+
|
|
150
|
+
writeFileSync(join(outputDir, 'dsh-github-ci.cordis.yml'), overlay)
|
|
151
|
+
writeFileSync(join(outputDir, 'task.txt'), taskText + '\n')
|
|
152
|
+
console.log(`dsh-github: overlay and task written to ${outputDir} (task: ${task}, engine: ${engine})`)
|