Skip to content

Exercise the hf_hub fake in CI, and fix the upload path it found - #934

Merged
zechengz merged 3 commits into
mainfrom
test/hf-integ-coverage
Aug 28, 2026
Merged

zechengz merged 3 commits into
mainfrom
test/hf-integ-coverage

Conversation

@zechengz

Copy link
Copy Markdown
Contributor

Follow-up to #931, which shipped the hf_hub resource, the hf CLI and the fake but no harness wiring, so CI started neither and ran no case against them. This adds the wiring plus 27 cases, and both hosts run all 27.

Writing the cases found a real bug in the code #931 shipped, which is the first commit here.

hf upload stored a file under its destination, not at it

hf upload <repo> <file> <path_in_repo> appended the source basename unconditionally, so hf upload r a.txt docs stored the file at docs/a.txt. The mount then reported docs as a directory and hf download docs returned Entry Not Found, so a file could be uploaded and never read back.

Upstream's _resolve_upload_paths only falls back to the basename when the operand is absent: path_in_repo is the destination file for a file source and the destination folder for a directory one. Settled two ways rather than guessed, since the two readings differ only on a case no unit test covered: upstream's source, and the real hf 0.35.3 binary pointed at our fake, where hf upload integ/repo-v1 ./a.txt docs leaves a tree of exactly ['docs'].

test_upload_prefixes_with_path_in_repo asserted docs/a.txt, so it had encoded the bug; it is corrected, and the file, directory and absent cases are pinned in both languages.

The fixture was empty

integ/fixtures/hf-hub/v1.json was {}, which is what made the service look wired: POST /reset accepted it and seeded nothing, so a mount had nothing to list. It now holds three repos, their commits and their main refs.

The cases

14 on the resource (integ/resources/hf_hub/repo.json), mirroring the shape of integ/resources/github/: ls, cat, head, wc, stat, find -name, find | wc -l, find -empty, du -s, grep -rl, grep -c, ENOENT, plus a dataset mount and a binary read.

13 on the CLI (integ/cli/hf.json), covering the flags rather than just the verbs: --include, --exclude, --revision, --local-dir, --force-download, --quiet, --repo-type, --exist-ok, --message, --yes, --commit-message, repo tag create|list|delete, repo-files delete with a glob, and all three 404 kinds, which are distinguishable only by X-Error-Code.

Two things the cases settled

A port collision. hf_hub's defaultPort was 5090, which is discord's port in the cli and chat facets, so the two fakes collided whenever both ran. Moved to 5086, outside the 5087-5099 block, with the goldens that embed the endpoint following it.

A stale-index constraint, not a bug. A CLI write does not invalidate the mount's index (indexTtl 86400, cachesReads true), so a mount read straight after a CLI write reads stale. The first draft of the CLI cases was flaky for exactly this reason; they now verify through hf download rather than through the mount. Worth knowing before anyone writes the next CLI case against a mount.

Verified

27/27 on python and 27/27 on typescript-node, re-run on this base after #932 landed. Python suite exit 0. pre-commit run --all-files green across all 20 hooks. pnpm -r typecheck clean. Case targets 2290 = baseline, layout parity 252 = baseline. CI wiring is bash -n swept and yaml-linted, but this is the first run of the new integ-battery-setup step and of the hf_hub server in the cli facet, so that is the part to watch here.

`hf upload <repo> <file> <path_in_repo>` appended the source basename
unconditionally, so the file landed at `<path_in_repo>/<basename>`. The
tree then reported `path_in_repo` as a directory and `hf download
<path_in_repo>` returned Entry Not Found, so a file could be uploaded
and never read back.

Upstream's `_resolve_upload_paths` only falls back to the basename when
the operand is absent: `path_in_repo` is the destination file for a file
source and the destination folder for a directory one. Confirmed against
the real `hf` 0.35.3 binary pointed at our fake, where `hf upload
integ/repo-v1 ./a.txt docs` leaves a tree of exactly `['docs']`.

`collect` now reports whether the source was a directory, and the caller
spreads only in that case. `test_upload_prefixes_with_path_in_repo`
asserted `docs/a.txt` and so encoded the bug; it is corrected, and the
file, directory and absent cases are pinned in both languages.
#931 shipped the resource, the CLI and the fake, but no target, so CI
never started the fake and never ran a case against it. This adds the
harness wiring and 27 cases, 14 on the resource and 13 on the CLI, and
both hosts run all of them.

`integ/fixtures/hf-hub/v1.json` was an empty object, which is why the
service looked wired: `POST /reset` accepted it and seeded nothing. It
now holds three repos, their commits and their `main` refs, so a mount
has something to list.

The resource cases mirror `integ/resources/github/`: ls, cat, head, wc,
stat, `find -name`, `find | wc -l`, `find -empty`, `du -s`, `grep -rl`,
`grep -c`, ENOENT, plus a dataset mount and a binary read. The CLI cases
cover the flags: `--include`, `--exclude`, `--revision`, `--local-dir`,
`--force-download`, `--quiet`, `--repo-type`, `--exist-ok`, `--message`,
`--yes`, `--commit-message`, `repo tag create|list|delete`, `repo-files
delete` with a glob, and all three 404 kinds.

Two things the cases settled:

`hf_hub`'s `defaultPort` was 5090, which is discord's port in the cli
and chat facets, so the two fakes collided whenever both ran. Moved to
5086, outside the 5087-5099 block, and the goldens that embed the
endpoint follow it.

A CLI write does not invalidate the mount's index (`indexTtl` 86400,
`cachesReads` true), so a mount read straight after a CLI write reads
stale. The CLI cases verify through `hf download` rather than through
the mount.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.

Tip: disable this comment in your organization's Code Review settings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8e8c7fefef

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread integ/runners/typescript/adapters.ts Outdated
The TypeScript adapter registered `hf_spaces` and then built it with
`HfModelsResource`: the kind was chosen by a ternary that read
`hf_datasets` and fell through to models for everything else. The three
resources differ only by the `repo_type` they send, so that does not
fail. It silently reads the models endpoints and reports the models
implementation as the one under test. Python names all three in a map
and had never had the gap.

Every kind is now named, and an unrecognized one throws rather than
becoming models. An absent `repo` throws too, for the same reason: a
Hub mount NAMES a repository, so `repoId: ''` would reach the fake as a
request for the repository called nothing.

Latent until now, since no target mounted a space. So the target gains
one, and a case reads it. Restoring the old ternary fails that case
with `cat: /space/one_byte.txt: No such file or directory`, which is
the models endpoint answering for a repository only the spaces endpoint
has.

28 cases now, both hosts.
@zechengz
zechengz merged commit d91e180 into main Aug 28, 2026
48 checks passed
@zechengz
zechengz deleted the test/hf-integ-coverage branch August 28, 2026 00:59
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.

1 participant