Skip to content

Commit e47cd5d

Browse files
committed
fix: 单次运行 button now triggers single_run.yml, not check.yml
The single-run button used to (a) overwrite the persisted COURSE_IDS secret with the basket contents and (b) fire check.yml — that clobbered the user's actual subscription list and ran the wrong workflow. The dedicated single_run.yml workflow already takes a course_ids input via workflow_dispatch, so add triggerSingleRunWorkflow() and dispatch it directly. COURSE_IDS secret is no longer touched by this flow.
1 parent a324c8b commit e47cd5d

2 files changed

Lines changed: 42 additions & 6 deletions

File tree

frontend/js/app.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -849,13 +849,13 @@ document.addEventListener("alpine:init", () => {
849849
this.singleRunTriggering = true;
850850
this.subsError = "";
851851
try {
852-
// Temporarily set COURSE_IDS to the single-run list, trigger,
853-
// then restore. This avoids a separate workflow input.
854-
await ICS.github.setCourseIdsSecret(
855-
this.repoOwner, this.repoName, creds.token, this.singleRunIds,
856-
);
857-
await ICS.github.triggerCheckWorkflow(
852+
// Fire single_run.yml directly with course_ids as input. This
853+
// keeps the persisted COURSE_IDS secret (used by daily check)
854+
// untouched, and uses the dedicated single-run workflow rather
855+
// than overloading the scheduled check workflow.
856+
await ICS.github.triggerSingleRunWorkflow(
858857
this.repoOwner, this.repoName, "main", creds.token,
858+
this.singleRunIds,
859859
);
860860
this._toast(
861861
"已触发单次运行,处理 " + this.singleRunIds.length + " 门课。请到 Actions 查看进度",

frontend/js/github.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,41 @@ async function _setCourseIdsSecret(owner, repo, token, courseIds) {
266266
return value;
267267
}
268268

269+
async function _triggerSingleRunWorkflow(owner, repo, ref, token, courseIds) {
270+
// Fires the Single Run workflow (single_run.yml) via workflow_dispatch.
271+
// The workflow takes a ``course_ids`` input (comma-separated list) and
272+
// processes ONLY those courses without touching the persisted
273+
// ``COURSE_IDS`` secret used by the daily check workflow.
274+
// PAT needs ``Actions: Read and write``.
275+
const url = `${_GH_API}/repos/${owner}/${repo}/actions/workflows/single_run.yml/dispatches`;
276+
const ids = (Array.isArray(courseIds) ? courseIds : [])
277+
.map(String).map((s) => s.trim()).filter(Boolean).join(",");
278+
if (!ids) throw new Error("单次运行列表为空");
279+
const res = await fetch(url, {
280+
method: "POST",
281+
headers: { ..._ghHeaders(token), "Content-Type": "application/json" },
282+
body: JSON.stringify({
283+
ref: ref || "main",
284+
inputs: { course_ids: ids },
285+
}),
286+
});
287+
if (res.status === 204) return;
288+
const body = await res.text();
289+
if (res.status === 403 || res.status === 404) {
290+
throw new Error(
291+
"无法触发 single_run workflow。请确认 PAT 已开启 Actions: Read and write " +
292+
`权限,且 single_run.yml 存在于 ref '${ref || "main"}'。服务端返回:${res.status} ${body}`
293+
);
294+
}
295+
if (res.status === 422) {
296+
throw new Error(
297+
"触发失败 (422):通常是 inputs 不匹配 workflow 定义,或 single_run.yml " +
298+
`不存在于指定分支 '${ref || "main"}'。服务端返回:${body}`
299+
);
300+
}
301+
throw new Error(`GitHub API error ${res.status}: ${body}`);
302+
}
303+
269304
async function _triggerCheckWorkflow(owner, repo, ref, token) {
270305
// Fires the iCourse Check workflow (check.yml) via workflow_dispatch.
271306
// The workflow uses ``secrets.COURSE_IDS`` directly — no inputs needed.
@@ -342,6 +377,7 @@ window.ICS.github = {
342377
fetchShardManifest: _fetchShardManifest,
343378
triggerExportWorkflow: _triggerExportWorkflow,
344379
triggerCheckWorkflow: _triggerCheckWorkflow,
380+
triggerSingleRunWorkflow: _triggerSingleRunWorkflow,
345381
getRepoPublicKey: _getRepoPublicKey,
346382
putRepoSecret: _putRepoSecret,
347383
setCourseIdsSecret: _setCourseIdsSecret,

0 commit comments

Comments
 (0)