Skip to content

ci: fix pre dryrun fail - #8

Merged
dongjiang1989 merged 8 commits into
masterfrom
fix-pre-dryrun-fail
May 29, 2026
Merged

ci: fix pre dryrun fail#8
dongjiang1989 merged 8 commits into
masterfrom
fix-pre-dryrun-fail

Conversation

@dongjiang1989

@dongjiang1989 dongjiang1989 commented May 29, 2026

Copy link
Copy Markdown
Member

Closes #7

Summary by CodeRabbit

  • Bug Fixes

    • Clearer permission error messages for repository upload failures.
    • Safer handling when snapshots are missing to avoid unexpected failures.
  • Improvements

    • Disk-aware file transfer strategy: small files transferred in parallel, large files sequentially with progress reporting.
    • More robust sync-state updates to prevent incorrect state when snapshots are absent.
  • Chores

    • Updated model repository reference and CI sync invocation.
  • Tests

    • Added tests covering snapshot failure scenarios and directional sync behavior.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 29, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 82ffe693-abf8-45fb-96f7-5761f81c20e4

📥 Commits

Reviewing files that changed from the base of the PR and between 726bb3d and eb128f8.

📒 Files selected for processing (1)
  • src/adapters/modelscope_adapter.py

📝 Walkthrough

Walkthrough

The PR refactors workflow CLI args into a bash array, surfaces adapter permission errors, validates required snapshots per sync direction, adds disk-aware transfer scheduling, conditions state persistence on actual transfers, and adds tests for snapshot-failure scenarios.

Changes

Sync Workflow Robustness

Layer / File(s) Summary
Workflow argument array construction
.github/workflows/sync.yml
The "Run sync" step refactors argument construction from string concatenation to a bash array, conditionally appending --dry-run, --direction, and --target flags and invoking with "${ARGS[@]}" for proper argument boundary preservation.
ModelScope adapter error handling
src/adapters/modelscope_adapter.py
upload_file and _upload_via_hf now detect authorization failures (HTTP 401/403, "does not exist") and raise PermissionError with explicit messaging. create_repo_if_needed replaces exception-based existence detection with explicit repo_exists checks and creates only when missing.
Sync engine snapshot validation
src/sync_engine.py
HuggingFace snapshot fetching wraps in try/except and logs warnings on failure. BIDIRECTIONAL mode raises RuntimeError if either snapshot is missing, HF_TO_MS raises if HuggingFace snapshot is missing, and MS_TO_HF validates the ModelScope snapshot presence.
File transfer scheduling optimization
src/sync_engine.py
Transfer execution implements disk-space-aware scheduling: small files (≤100MB) transfer in parallel using a bounded thread pool, large files transfer sequentially with indexed progress logging, and docstring documents the strategy.
Sync engine state persistence and fallbacks
src/sync_engine.py
State updates occur only when result.files_synced is non-empty. Per-file SHA lookups fall back to the alternate snapshot's file map when the primary map lacks the entry. HF last_synced_commit is set only when hf_snapshot exists. CLI exit behavior uses an explicit any_failed variable.
Snapshot failure tests and model configuration
tests/test_sync_engine_extended.py, config/sync_config.yaml
Three new tests validate bidirectional and unidirectional sync behavior when snapshots fail: both sides failing marks FAILED, one side failing marks FAILED with error message, and HF failure does not prevent MS_TO_HF success. The qwen2.5-7b-instruct model's ms_repo_id is updated to a new repository path.

Sequence Diagram

sequenceDiagram
  participant Workflow
  participant SyncEngine
  participant HuggingFace
  participant ModelScope
  Workflow->>SyncEngine: invoke python -m src.sync_engine
  SyncEngine->>HuggingFace: fetch snapshot (try/except)
  SyncEngine->>ModelScope: fetch snapshot
  SyncEngine->>SyncEngine: schedule transfers (small parallel, large sequential)
  SyncEngine->>ModelScope: upload files via ModelScopeAdapter
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I nudge the args into a row,
I sniff for perms where uploads go,
I sort the files, small quick, big slow,
I only mark the state when bytes did flow,
Hopping home with tests aglow.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'ci: fix pre dryrun fail' is vague and does not clearly communicate the specific changes made in the pull request. Provide a more descriptive title that clearly explains the specific issue being fixed, such as 'ci: improve snapshot handling and error resilience in sync workflow' or similar.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The PR addresses issue #7 (sync failure on 2026-05-29) with multiple robustness improvements including snapshot handling, error handling, and performance optimizations.
Out of Scope Changes check ✅ Passed All changes appear scoped to fixing sync failures: workflow improvements, adapter error handling, sync engine robustness, config updates, and related tests.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-pre-dryrun-fail

Comment @coderabbitai help to get the list of available commands and usage tips.

sync.yml:
- Fix word-splitting bug: replace string ARGS with bash array,
  same issue as entrypoint.sh (PR #1 review)

sync_engine.py:
- Wrap HF snapshot fetch in try/except (was unprotected, unlike MS)
- Add explicit guard: HF_TO_MS fails clearly when HF snapshot unavailable
- Add explicit guard: BIDIRECTIONAL fails clearly when both snapshots unavailable
- Fix _update_state: handle None hf_snapshot (was causing AttributeError)
- Change exit code: only exit(1) when ALL items fail, not on partial failure

tests:
- test_both_snapshots_fail_bidirectional: both adapters fail → FAILED
- test_hf_snapshot_fails_ms_to_hf_ok: HF fails but MS_TO_HF only
  needs MS snapshot → SUCCESS (exposes _update_state bug that was fixed)

Signed-off-by: dongjiang <dongjiang1989@126.com>
Address PR #4 review from gemini-code-assist:

1. BIDIRECTIONAL: change `and` to `or` in snapshot None check.
   Both snapshots are required for bidirectional sync — if either
   is None, detect_bidirectional() crashes with AttributeError on
   the None snapshot. Now raises RuntimeError with specific status
   per adapter (e.g. "HF=OK, MS=FAILED").

2. Exit code: revert to exit(1) on any failure (not just all-fail).
   CI/CD downstream steps already use `if: always()` so they run
   regardless of exit code. Returning 0 on partial failure would
   silently mask errors in automated pipelines.

+1 test: test_one_snapshot_fails_bidirectional

Signed-off-by: dongjiang <dongjiang1989@126.com>
Problem analysis from failed sync run (151s, exit code 1, empty .sync_state/):

1. Disk space: 4 parallel downloads of Qwen2.5-7B (~14GB total) fills
   up the GitHub Actions runner (~14GB). Fix: large files (>100MB)
   transfer sequentially (download→upload→delete→next), small files
   still use parallel.

2. create_repo_if_needed: was calling get_repo_snapshot (full file
   listing) just to check if repo exists. Fix: use repo_exists() which
   is a lightweight API call. Also wrap in try/except to be non-fatal.

3. _update_state: only called on full success, so partial transfers
   were lost. Fix: call _update_state whenever files_synced is non-empty,
   so successfully transferred files are recorded and won't be re-synced.

Signed-off-by: dongjiang <dongjiang1989@126.com>
…ate update

PR #6 review fixes (2 of 3 comments valid):

1. modelscope_adapter.py: Pass repo_type parameter to create_repo()
   - Without this, dataset repos were incorrectly created as model repos
   - ModelScope SDK defaults repo_type='model' when not specified

2. sync_engine.py: Cross-reference file maps when updating sync state
   - When syncing MS→HF, the synced file's SHA is in ms_file_map, not hf_file_map
   - Without fallback, synced_files wouldn't be recorded in state
   - Now tries both maps: hf_file_map.get(fp) or ms_file_map.get(fp)
   - Same logic for MS state: ms_file_map.get(fp) or hf_file_map.get(fp)

Comment 1 (repo_exists method) was invalid: HubApi.repo_exists() does exist
in the ModelScope SDK (verified: returns bool, accepts repo_type parameter).

Signed-off-by: dongjiang <dongjiang1989@126.com>
When uploading to ModelScope fails due to lack of write access, the API
returns a misleading "resource does not exist" error. This commit adds
explicit error detection for permission failures (401/403/"does not exist")
and raises a clear PermissionError with actionable guidance:

- Tells the user they don't have write access
- Suggests using their own namespace (e.g., 'username/model-name')
- Applies to both SDK upload and HF fallback upload paths

This prevents confusing errors when users try to sync to repos they
don't own (e.g., 'Qwen/Qwen2.5-7B-Instruct' instead of their own repo).

Signed-off-by: dongjiang <dongjiang1989@126.com>
The previous ms_repo_id 'Qwen/Qwen2.5-7B-Instruct' belongs to the
Qwen organization and requires write access that external users do
not have. Changed to 'dongjiang1989/Qwen2.5-7B-Instruct' so the
sync can create and upload to a repo under the user's own namespace.

Signed-off-by: dongjiang <dongjiang@kubeservice.com>
Signed-off-by: dongjiang <dongjiang1989@126.com>
@dongjiang1989
dongjiang1989 force-pushed the fix-pre-dryrun-fail branch from bf04b38 to 726bb3d Compare May 29, 2026 13:37

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request updates the sync configuration, improves error handling for ModelScope uploads, introduces disk-space-aware sequential transfers for large files, and adds robust snapshot validation checks. The code review highlights a critical runtime AttributeError due to the use of non-existent repo_exists and create_repo methods on ModelScope's HubApi. Additionally, the reviewer suggests converting exception messages to lowercase for case-insensitive matching and ensuring both snapshots are valid during HF_TO_MS syncs to prevent redundant file transfers.

Comment thread src/adapters/modelscope_adapter.py
Comment thread src/adapters/modelscope_adapter.py Outdated
Comment thread src/adapters/modelscope_adapter.py Outdated
Comment thread src/sync_engine.py
Use str(e).lower() when matching error messages so that variants
like "Does Not Exist", "Forbidden", or "FORBIDDEN" are all caught.
Also added "forbidden" as an additional keyword to match.

Addresses gemini-code-assist review on PR #8.

Signed-off-by: dongjiang <dongjiang@kubeservice.com>
Signed-off-by: dongjiang <dongjiang1989@126.com>
Refactor long `or` chain into `any()` with a tuple of keywords to
keep lines under 100 chars.

Signed-off-by: dongjiang <dongjiang@kubeservice.com>
Signed-off-by: dongjiang <dongjiang1989@126.com>
@dongjiang1989
dongjiang1989 merged commit 98bee3a into master May 29, 2026
11 of 12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sync failure on 2026-05-29

1 participant