What:在 pkg-update 技能的步驟 3.5 新增註解界線規則,並在 README.md 的 pkg-update 段落同步同一份指引。 Why:套件更新途中常會為了鎖版本或繞道不相容而留註解,過去沒有界線,容易把文件相關資訊寫進程式碼註解,造成註解與文件重複、且內容很快過期。 How:規則正文留在 jsc-review 的 references/comment-scope.md,這裡只放指引與連結、不重複清單。註解只寫鎖版本或繞道的原因;第三方套件的 issue 連結屬白名單,用來說明繞道成因與解除條件;內部議題編號、工作包編號、人名與 @ 提及、產生來源署名一律不得寫。步驟 3.5 另附可檢核的完成條件,並指向 jsc-hooks 的 comment-scope.sh 即時告警與修正回檢流程。 Who:jsc-pkg 的 pkg-update 技能,以及 README.md 的技能說明區塊。
55 lines
8.0 KiB
Markdown
55 lines
8.0 KiB
Markdown
---
|
|
name: pkg-update
|
|
description: Update every external package of a project to its latest stable version using list-packages.sh and latest-version.sh, then run build and tests. Revert all changes on failure. Supports nodejs, python, and dotnet projects. Use for dependency refresh; not for adding or removing packages.
|
|
---
|
|
|
|
# pkg-update — batch-update packages
|
|
|
|
## Exit-code routes
|
|
|
|
Every tool exit code below has exactly one route. Three routes exist:
|
|
|
|
- **skip** — record the reason, keep going.
|
|
- **stop** — report and end the run. Change no file, and never enter step 5.
|
|
- **revert** — go to step 5, which reverts the working tree.
|
|
|
|
Only a real install, build or test failure takes the revert route. A missing input, a bad argument, an unknown ecosystem or a missing command is a broken call or a broken toolchain, so it takes the stop route.
|
|
|
|
One number carries one meaning across all five tools. Exit 6 is always a missing project directory and always stops the run — never fold it into the exit 3 skip, or a bad path hides as "nothing to do".
|
|
|
|
| Tool | 0 | 1 (bad argument count) | 2 (unknown ecosystem) | 3 (no source file) | 4 | 5 | 6 (project dir not found) | other |
|
|
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
| `list-packages.sh` | continue | stop | — | — | stop (python3 missing) | — | stop | stop |
|
|
| `latest-version.sh` | continue | stop | stop | — | skip (not in registry) | stop (curl or python3 missing) | — (takes no project dir) | stop |
|
|
| `apply-version.sh` | continue | stop | stop | skip | skip (package absent from the file) | stop (python3 missing) | stop | stop |
|
|
| `install-deps.sh` | continue | stop | stop | skip | stop (npm, pip or dotnet missing) | — | stop | **revert** |
|
|
| `build-test.sh` | continue | stop | stop | — (uses 5 instead) | stop (npm, python3, pytest or dotnet missing) | ask the user | stop | **revert** |
|
|
|
|
Exit 4 and exit 5 are the two codes whose meaning depends on the tool, so read them off this table rather than from memory.
|
|
|
|
## Steps
|
|
|
|
1. Run `tools/list-packages.sh {project dir}` to get every external package (ecosystem, name, current version). Route the exit code per the table above. Step 1 is done only when the tool exited 0 and at least one row came back, with an ecosystem, a name and a current version in every row. Zero rows → stop and report the project directory you scanned plus the supported ecosystems (nodejs / python / dotnet), and run no further step.
|
|
2. Prove the project directory is a git repository with a clean tree. Run this before any step changes a file:
|
|
1. Run `git -C {project dir} rev-parse --git-dir`. Exit 0 is required to continue, because step 5's revert is impossible outside a git repository. Any other exit code → stop and report the directory, and run no further step.
|
|
2. Run `git -C {project dir} status --porcelain`. Continuing requires that it prints **nothing at all**. Any output stops the run and reports that output, **including `??` untracked lines**: step 5 runs `git clean -fd`, which deletes untracked files with no reflog and no way back.
|
|
3. Step 2 is done only when `rev-parse --git-dir` exited 0 and `status --porcelain` printed zero bytes. Report both results, then enter step 3.
|
|
3. Update ecosystem by ecosystem. This step **MUST run as a sub agent** (one sub agent per ecosystem):
|
|
1. For every package, run `tools/latest-version.sh {ecosystem} {name}` for the latest stable version, then `tools/apply-version.sh {ecosystem} {project dir} {name} {version}` to rewrite the version source file (package.json / requirements.txt / pyproject.toml / *.csproj). This substep is done when every package of the ecosystem carries either an applied version or a skip reason from substep 2.
|
|
2. Route every exit code per the table above. The skip route covers `latest-version.sh` exit 4 (package not found in the registry), `apply-version.sh` exit 3 (no version source file) and `apply-version.sh` exit 4 (package absent from the file): record the package and the reason, move on to the next package, and never abort the whole ecosystem. The stop route covers exit 1, exit 2, `latest-version.sh` or `apply-version.sh` exit 5 (a required command is missing) and `apply-version.sh` exit 6 (project directory not found): report the code and end the run without entering step 5. This substep is done when every exit code seen has taken exactly one route.
|
|
3. Run `tools/install-deps.sh {ecosystem} {project dir}` once, after every package of that ecosystem is applied. Exit 0 means the install finished. Exit 3 means this ecosystem has no dependency source file, which is the same documented skip as substep 2: record the ecosystem and the reason, and install nothing. Exit 1, exit 2, exit 4 and exit 6 take the stop route — exit 6 is a missing project directory, so report it instead of skipping it. Only another non-zero code is a real install failure and goes to step 5. This substep is done when the exit code is recorded together with the route it took.
|
|
4. The sub agent returns one row per package from substep 1: name, old version, new version — or `skipped` plus the reason. It also returns the `install-deps.sh` exit code and its route. The ecosystem is done only when every package appears in exactly one row.
|
|
5. **Comments this step writes.** Holding a package at an older version, or coding around an incompatibility, sometimes needs a comment in the version source file or in the code. Write **why** the pin or the workaround exists, never a tracking number. The one this skill trips over most: **a third-party package's issue link is on the allow list** — it is what states the cause of the workaround and the condition for removing it, as in `// works around github.com/foo/bar/issues/88; drop this pin once that ships`. Out of a comment: internal issue ids, work package ids, personal names, `@` mentions and generated-by credits. Full list and allow list: `jsc-review/references/comment-scope.md`. `jsc-hooks/hooks/comment-scope.sh` compares every write against that list right after the file is written and prints a warning on a hit; fix the comment on the spot, then continue this step. Completion condition: every comment line this step added names a reason, carries no internal issue id, work package id, personal name, `@` mention or generated-by credit, and every `comment-scope.sh` warning this step received has been fixed and re-checked with no warning left.
|
|
4. Run `tools/build-test.sh {ecosystem} {project dir}` for every ecosystem and route on the exit code:
|
|
- 0 → this ecosystem passed.
|
|
- 1, 2, 4 or 6 → stop route. Report the code and the missing argument, ecosystem, command or directory, and enter no further step. Exit 4 means the toolchain is broken, not that the packages are broken, so reverting would destroy files for nothing.
|
|
- 5 → no build or test command could be inferred. Ask the user for the build command and the test command per the `jsc-ask:ask` rules, run the answers in that order, and take their exit codes as this ecosystem's result: all 0 → passed; any non-zero → step 5.
|
|
- any other code → a real build or test failure. Go to step 5.
|
|
|
|
Step 4 is done only when every ecosystem reached exit 0, from the tool or from the user's own commands.
|
|
5. A real install, build or test failure reached this step → revert:
|
|
1. Run `git -C {project dir} checkout -- .` to restore every tracked file to HEAD.
|
|
2. Run `git -C {project dir} clean -fd` to remove the untracked files and directories this run created, such as a new lock file. Gitignored paths survive `-fd` on purpose: `node_modules`, `__pycache__`, `bin/` and `obj/` stay behind, so restoring install output is out of scope for this skill. Do not reach for `-fdx` — it deletes far more than this run created.
|
|
3. The revert is done only when `git -C {project dir} status --porcelain` prints nothing. Report the failing packages with an error summary after that check passes.
|
|
6. Success → report the update list (package, old version, new version), plus every skip and its reason, and hand off to `jsc-git:commit`. Step 6 is done when the hand-off is made and every package from step 1 appears either as an update or as a skip.
|