Skip to content

send-file.sh 过期:缺少必填 flag 且会将项目全部文件打入 ZIP#52

Merged
Svtter merged 23 commits into
mainfrom
ralph/issue-50
May 15, 2026
Merged

send-file.sh 过期:缺少必填 flag 且会将项目全部文件打入 ZIP#52
Svtter merged 23 commits into
mainfrom
ralph/issue-50

Conversation

@Svtter
Copy link
Copy Markdown
Contributor

@Svtter Svtter commented May 14, 2026

Problem

scripts/send-file.sh had two breaking issues:

  1. Missing required flags: sth send requires --tag, --category, and --project, but send-file.sh never passed them, causing every invocation to fail with --tag is required.
  2. ZIP bloat from project directory: sth send uses the HTML file's parent directory as the archive root. When the HTML lives inside a large project repo, every file in the repo gets packed into the ZIP, triggering the server-side uploaded archive contains too many files limit.

Approach

Rewrite send-file.sh to accept and forward the required flags, and isolate the HTML file before uploading:

  • Flag parsing: Full CLI parser supporting --tag, --category, --project, and --server (with --flag=VALUE syntax). Empty/whitespace values are rejected with clear errors. A --help flag prints usage.
  • Temp directory isolation: The HTML file is cp'd into a mktemp -d with chmod 700, so only that single file is packaged into the upload ZIP. An EXIT trap cleans up the temp dir after sth send completes (exec replaced with direct call so the trap fires).
  • Robust path resolution: Uses realpath with readlink -f and cd+pwd fallbacks for cross-platform compatibility. Validates the file exists and has an .html/.htm extension before proceeding.
  • Updated docs: SKILL.md now shows the required flags in the usage example and documents the temp-dir isolation behavior, with a note to use sth send directly when sibling resources are needed.

Tests

  • Manual verification: send-file.sh rejects invocations missing --tag/--category/--project with specific error messages.
  • --help and -h print usage and exit.
  • HTML file is correctly copied to an isolated temp directory; only that file appears in the upload.
  • Path resolution works with realpath, readlink -f, and the cd+pwd fallback.
  • Non-HTML files are rejected with an extension check.
  • --flag=VALUE and --flag VALUE syntax both work; empty values (including --flag= with trailing whitespace) are caught.

Closes #50

Agent added 21 commits May 14, 2026 22:20
…late HTML in temp dir

Fixes two issues with send-file.sh:
1. Pass --tag, --category, --project to sth send (now required by CLI)
2. Copy HTML to a temp directory before sending to avoid packaging
   the entire project directory into the upload ZIP
…ards for --flag= syntax

- Replace exec with direct invocation so trap cleanup EXIT fires and
  temp directory is properly removed after upload
- Add empty-value validation for --tag=, --category=, --project= forms
- Simplify redundant directory existence check before file check
Review feedback: --server=* branch was missing the same empty-value
validation that --tag=*, --category=*, and --project=* already had.
Replace cd+pwd+basename with realpath(1) for resolving the target file
path, as suggested by review. This handles symlinks correctly and is
more semantically clear.
After the argument parsing loop, $1 is empty because all positional
parameters have been consumed. Save the original filename before
calling realpath so the error message is actually helpful.
…m realpath, signal traps

- Unify --flag= empty value error messages to match --flag format
- Add SIGINT/SIGTERM traps alongside EXIT for tmpdir cleanup
- Add macOS-compatible realpath fallback using dirname/pwd
- Document sibling resource workflow in SKILL.md
Address review feedback: initialize tmpdir="" before mktemp and use
${tmpdir:-} in cleanup to be robust under set -u.
…nsion check

Move trim operation before required parameter checks so whitespace-only
values (e.g. --tag '   ') are caught. Add .html/.htm extension validation
to prevent accidental non-HTML uploads.
…path fallback

- Replace ${filename,,} with tr for macOS Bash 3.2 compatibility
- Move trim() function definition to top with other helpers
- Pre-extract basename before cd in fallback path resolution
…implify path fallback

- Extract require_value() helper to reduce duplicated option validation
- Accept values starting with '-' (remove false-positive rejection)
- Make cd+pwd path fallback error handling more explicit
…-f compat

- Probe readlink -f with a known path (/) before using it, so macOS
  BSD readlink falls through to the cd+pwd fallback instead of
  emitting a misleading 'file not found' error.
- Replace allowed_exts loop with a case statement for extension
  matching, improving readability.
@github-actions
Copy link
Copy Markdown

无遗漏

PR 完整实现了 Issue #50 中提出的两个需求:

  1. --tag / --category / --project 参数透传send-file.sh 新增了完整的 CLI 参数解析(含 --flag=VALUE 语法),对所有三个必填参数进行空值校验后透传给 sth send。Issue 中"提供合理的默认值"作为可选项,PR 选择要求显式传递,是合理且更安全的做法。

  2. 临时目录隔离:新增 mktemp -d + chmod 700 + EXIT trap cleanup 机制,将 HTML 文件复制到隔离目录后上传;同时将 exec 改为直接调用,确保 trap 能触发清理。SKILL.md 同步更新了用例如和需要同级资源时直接使用 sth send 的说明。

附加实现(Issue 未明确要求但 PR body 承诺的)也全部到位:路径解析三种 fallback、扩展名校验、--help/-h 用法提示、server URL 格式校验、空值/空白值拒绝。无遗漏。

New%20session%20-%202026-05-14T14%3A21%3A33.869Z
opencode session  |  github run

@github-actions
Copy link
Copy Markdown

有条件合并

审查摘要

整体代码质量较高,逻辑清晰,错误处理完整,安全性处理得当。但有以下几个需要注意的问题。

阻塞项

  1. --help/-h 退出码错误 (send-file.sh:18) — usage() 函数固定 exit 1,但 --help-h 属于正常使用场景(第 30-32 行显式调用了 usage),应 exit 0。当前实现下 send-file.sh --help; echo $? 会输出 1,不符合惯例,可能影响自动化脚本的判断。建议将 help 路径与错误路径分离。

建议项

  1. echo "$filename" 的安全隐患 (send-file.sh:129) — 若文件名以 - 开头(如 -n.html),echo 在某些 shell 实现下可能将其解释为选项。建议改为 printf '%s' "$filename"

  2. bootstrap-repo.sh stdout 的隐式契约 (send-file.sh:143) — repo_dir="$("$script_dir/bootstrap-repo.sh")" 依赖 bootstrap 脚本仅输出路径到 stdout。当前 bootstrap-repo.sh 满足此契约(go build 输出已重定向到 stderr),但这是一个脆弱约定,后续如果有人向 bootstrap 脚本添加调试输出就会静默破坏。建议加一个 [ -d "$repo_dir" ] 校验。

  3. 缺少 // 0 注释 — 无实质影响,但按 set -euo pipefail 风格,建议在行末显式注释意图(可选)。

New%20session%20-%202026-05-14T14%3A21%3A35.879Z
opencode session  |  github run

- usage() now accepts exit code parameter; --help/-h exit 0, errors exit 1
- Replace echo with printf for filename to avoid dash-prefixed filename issues
- Add directory validation for bootstrap-repo.sh output
@github-actions
Copy link
Copy Markdown

发现遗漏

分析

经逐条比对 Issue #50 的需求与 PR 实现代码:

需求 实现 状态
接受 --tag/--category/--project 并透传 send-file.sh:47-61 解析,:154-158 透传
空值拒绝(或提供合理默认值) trim() + 空值校验 :88-99,选择严格拒绝
临时目录隔离 HTML 文件 mktemp -d + chmod 700 + cp :138-143
EXIT trap 清理 trap cleanup EXIT + 去掉 exec
路径解析 fallback realpath / readlink -f / cd+pwd :101-126
扩展名 .html/.htm 校验 :131-136
--help 打印用法 :33-34 + :45-46
SKILL.md 文档同步 新增 flags 示例和临时目录说明

Issue #50 的两项核心需求(必填参数透传、临时目录隔离)及 PR body 中声明的全部附加特性均已实现,代码中没有遗漏任何 spec 要求的特性。无遗漏。

New%20session%20-%202026-05-14T14%3A41%3A45.104Z
opencode session  |  github run

@github-actions
Copy link
Copy Markdown

有条件合并

审查摘要

整体代码质量高:参数解析完整、错误处理周到、临时目录隔离方案正确(EXIT trap + chmod 700)、路径解析三种 fallback 稳健。但有一个阻塞问题。

阻塞项

  1. usage 函数在 help 路径与错误路径间存在不一致的行为 (send-file.sh:18, 67-68, 73)

    当未知选项(-* case,第 68 行)或多余参数(第 73 行)触发 usage 时,usage 会向 stderr 输出 help 文本并以 exit 1 退出。但这本身是正确的行为,因为确实发生了错误。

    实际需要关注的 blocking issue 是:第 67-68 行的 -* case 会将 --(POSIX end-of-options)当作未知选项拒绝,导致无法传递以 - 开头的文件名:

    send-file.sh -- -foo.html --tag t --category c --project p
    # Error: Unknown option: --

    这在 CI/CD 自动化中可能遇到(例如从工具输出中拿到 -results.html 这样的临时文件)。

    修复方案:在 -*) 前加一个 --) case:

    --) shift; break ;;

建议项

  1. echo "$filename" 的安全隐患 (send-file.sh:135) — 若文件名以 -n 开头,echo 在某些 shell 中会被解析为选项。建议改为 printf '%s\n' "$filename"

  2. 脚本末尾 sth send 缺少失败后的错误提示 (lines 154-158) — set -e 会在 sth send 失败时立即退出,但不会输出除 sth 自身 stderr 外的额外提示。如果用户只看到 shell 错误而没有上下文,可能难以排查。建议加一句失败提示或保留退出码:

    if ! "$repo_dir/dist/sth" send ...; then
      echo "Error: sth send failed" >&2
      exit 1
    fi
  3. $tmpdir/$filename 可能拼接出不存在的路径 — 虽然 cp 在前面成功了,但理论上如果 $filename 含有路径分隔符(如 ../../etc),basename 已确保不包含 /,因此无实际风险。仅作提示。

非阻塞说明:先前 reviewer 提到的"usage exit code 问题"实际已正确实现(usage 0 走 exit 0),此条不成立。

New%20session%20-%202026-05-14T14%3A41%3A44.993Z
opencode session  |  github run

Add a --) case before the catch-all -* so that -- is properly recognized
as the POSIX end-of-options marker, allowing filenames starting with -.
@github-actions
Copy link
Copy Markdown

无遗漏

Issue #50 的两项核心需求(--tag/--category/--project 参数透传、临时目录隔离避免 ZIP 膨胀)及 PR body 声明的全部附加特性均已完整实现:

  • 参数解析:--flag=VALUE--flag VALUE 双语法,空值/空白值严格拒绝
  • 临时目录:mktemp -d + chmod 700 + cp + EXIT trap 清理,已去掉 exec 确保 trap 触发
  • 路径解析:realpathreadlink -fcd+pwd 三层 fallback
  • 扩展名校验:拒绝非 .html/.htm 文件
  • --help/-h 用法输出(exit 0)
  • Server URL 格式校验
  • SKILL.md 同步更新:flags 示例、临时目录说明、sth send 直接使用指引

未发现 spec 提及但未实现的任何特性。

New%20session%20-%202026-05-14T14%3A45%3A56.754Z
opencode session  |  github run

@github-actions
Copy link
Copy Markdown

可合并

代码质量高:必填参数解析和空值校验完整,临时目录隔离方案正确(mktemp + chmod 700 + EXIT trap cleanup),路径解析三种 fallback 稳健,文件扩展名校验、--help 支持、server URL 格式校验均有覆盖。之前审查者提到的 blocking issues(--help 退出码、-- 选项终止符、echo 安全性)在当前 HEAD 中均已不复存在或本来就不是问题。

阻塞项:无

建议项:

  • Server URL 校验后缺少 usage 提示 (send-file.sh:88) — exit 1 直接退出而未调用 usage,与其他校验路径(tag/category/project 缺失时调用 usage)不一致,建议统一为 usage 以提供更完整的提示
  • sth send 失败时无额外上下文 (line 156) — 依赖 set -e 处理失败,exit trap 能正确清理临时目录,但用户只看到 sth 自身的 stderr;若希望在脚本层面给出更清晰的上下文,可在调用前加一条提示或调用后捕获退出码
  • bootstrap-repo.sh stdout 契约 (line 148) — repo_dir 捕获 stdout,当前 bootstrap-repo.sh 满足只输出路径的约定(go build 输出已重定向到 stderr),且 line 149 的 [ -d "$repo_dir" ] 校验提供了安全网,但仍是隐式协议,建议在 bootstrap-repo.sh 或此处补充注释说明

New%20session%20-%202026-05-14T14%3A46%3A01.051Z
opencode session  |  github run

@Svtter Svtter merged commit bddeaa6 into main May 15, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

send-file.sh 过期:缺少必填 flag 且会将项目全部文件打入 ZIP

1 participant