Skip to content

feat(modelsync): Model Sync Option A, Separate Model Sync Page on the Replication Copy Flow - #24318

Draft
Vad1mo wants to merge 8 commits into
goharbor:mainfrom
Vad1mo:feat/model-sync-option-a
Draft

Vad1mo wants to merge 8 commits into
goharbor:mainfrom
Vad1mo:feat/model-sync-option-a

Conversation

@Vad1mo

@Vad1mo Vad1mo commented Nov 5, 2026 •

Copy link
Copy Markdown
Member

Thank you for contributing to Harbor!

Comprehensive Summary of your change

Draft for the design discussion in goharbor/community#297. Not meant to be merged as is. This is Option A of two prototypes compared in #297 (comment); Option B is #24319.

Option A: a separate Administration > Model Sync product surface, modelled on the proposal and the model-poc PoC, running on the shared backend:

  • own model_sync_policy table (0200_2.17.0_schema.up.sql) and /model-sync/* API, same paths and shapes as the PoC, plus exclude filters
  • system-admin portal module (policy list, create/edit with "Resolve source" preview, executions, tasks, logs), ported from the PoC
  • runs use the vendor type MODEL_SYNC but execute through the existing replication copy flow, transfer, job and execution/task tables. No second packer or transfer.

Stack

This branch contains three layers. Please review only the last one:

  1. feat(replication): Hugging Face registry adapter for replication and proxy cache (WIP) #24008: Hugging Face registry adapter (2 commits)
  2. Model-import foundation, shared with Option B (4 commits): file filter with include/exclude, ArtifactResolver for copy previews, optional sha-<12> revision tag, source_only in RegistryInfo
  3. Option A (2 commits): feat(modelsync): Add Model Sync Policies on the Replication Copy Flow, feat(portal): Add Model Sync Administration Page

GitHub can't stack PRs from a fork onto #24008, so the base is main and the diff includes layers 1 and 2.

Verified

  • HuggingFaceTB/SmolLM2-135M @ main, include *.json: sha256:2dc8fb68cff37ff1… with tags main and sha-93efa2f097d5; rerun skipped with the same digest. Same result as Option B.
  • go build/vet per commit; go test on pkg/reg/..., controller/replication/..., controller/registry/..., server/v2.0/handler/..., controller/modelsync/..., pkg/modelsync/...; DB-tagged tests against Postgres with all migrations applied
  • ng build, model-sync karma specs 23/23

Limitations

  • one policy is one model, no org/**
  • a revision must be a branch or tag; a pinned commit is not accepted (copy flow lists ref heads)
  • no proxy cache path
  • replication needed a non-persisted DestRepository override because its namespace rewrite always keeps the source's last path component
  • en-us strings only

Screenshots

A1: Model Sync entry in Administration

A1: Model Sync entry in Administration

A2: Policy list

A2: Policy list

A3: Policy form with resolved preview (include *.json, exclude onnx/, .bin)*

A3: Policy form with resolved preview (include *.json, exclude onnx/**, *.bin)

A4: Executions

A4: Executions

A5: Task list with log link

A5: Task list with log link

A6: Resulting model artifact. The raw descriptor JSON is today's artifact view; the Model panel in Option B is independent of the import path and would work here too

A6: Resulting model artifact. The raw descriptor JSON is today's artifact view; the Model panel in Option B is independent of the import path and would work here too

A7: Rerun skipped with the same digest

A7: Rerun skipped with the same digest

Issue being fixed

Related: goharbor/community#297, depends on #24008

Please indicate you've done the following:

  • Well Written Title and Summary of the PR
  • Label the PR as needed. "release-note/ignore-for-release, release-note/new-feature, release-note/update, release-note/enhancement, release-note/community, release-note/breaking-change, release-note/docs, release-note/infra, release-note/deprecation"
  • Accepted the DCO. Commits without the DCO will delay acceptance.
  • Made sure tests are passing and test coverage is added if needed.
  • Considered the docs impact and opened a new docs issue or PR with docs changes if needed in website repository.

Vad1mo and others added 3 commits November 5, 2026 09:38
Add a `huggingface` registry type that lets pull replication and proxy
cache copy Hugging Face Hub models into Harbor as ModelPack model-spec
artifacts, without a dedicated sync framework.

The adapter synthesizes a byte-deterministic OCI manifest from the Hub
API for a pinned commit: one raw layer per file, LFS sha256 reused as the
layer digest, non-LFS files hashed and checked against their git blob id,
file classification frozen from modctl. The same commit always yields the
same digest, so replication's digest-equality skip and proxy cache's
local/remote comparison work unchanged.

Digest-to-file lookups go through lib/cache scoped per registry (Redis in
core, in-process memory in jobservice) with a stateless rebuild fallback,
because proxy cache creates a new adapter per request.

The type is source-only: replication policies with a Hugging Face
destination are rejected.

Refs: goharbor/community#297
Signed-off-by: Vadim Bauer <vb@container-registry.com>
…s, propagate lookup errors

Signed-off-by: Vadim Bauer <vadim@8gears.com>
Add a generic "file" replication filter that limits which files a source
adapter packs into an artifact. The policy's filter becomes
model.SourceOptions, which the copy flow hands to the source adapter through
the optional adapter.SourceConfigurer interface and serializes with the source
resource, so the transfer configures its own adapter the same way. Adapters
that do not implement the interface fail instead of ignoring the options.

The Hugging Face adapter selects files with the filter before hashing and
synthesis. The digest depends on the commit and the selected files only, so
the same filter always yields the same digest and a filter that drops files
yields a different one.

Signed-off-by: Vad1mo <vadim@8gears.com>
@Vad1mo
Vad1mo force-pushed the feat/model-sync-option-a branch from 4595753 to e7675b8 Compare November 5, 2026 08:50
Add the optional adapter.ArtifactResolver interface. Resolve reports what a
copy of one source reference would produce without copying: the revision,
the moving tags pointing at it, license, task, the file list with class,
size, sha256 and whether the file filter selects it, matched totals, and the
manifest digest of the copy.

The Hugging Face adapter implements it with the same snapshot, hashing and
synthesis code as the copy, so the previewed digest is the copied digest. The
Hub's pipeline_tag is read into the snapshot as the task. A live test behind
the hubintegration build tag resolves against the public Hub.

Signed-off-by: Vad1mo <vadim@8gears.com>
Add a revision_tag flag to replication policies. With it, every copy also
gets the immutable tag sha-<first 12 hex of the source revision> next to its
moving tags, so a scheduled pull of main keeps every imported revision
addressable. The flag travels with the other source options to the source
adapter; policy validation accepts it only for sources whose registry info
declares supported_revision_tag.

The Hugging Face adapter appends the revision tag after the tag filter and
resolves a revision tag back to the ref head it names. The column is added
idempotently in the 2.17.0 schema migration.

Signed-off-by: Vad1mo <vadim@8gears.com>
Add source_only to the registry info. Policy validation now rejects any
registry that declares it as a replication destination instead of checking
for the Hugging Face type, and the registry info API returns the flag so a
UI can hide such registries from destination pickers. The local Harbor is
never probed, and a registry whose capabilities cannot be read is accepted as
before.

Signed-off-by: Vad1mo <vadim@8gears.com>
Signed-off-by: Vad1mo <vadim@8gears.com>
@Vad1mo
Vad1mo force-pushed the feat/model-sync-option-a branch from e7675b8 to 5921d3d Compare November 5, 2026 09:18
@codecov

codecov Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 71.47239% with 744 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.86%. Comparing base (46d05cb) to head (5921d3d).

Files with missing lines Patch % Lines
...pkg/reg/adapter/huggingface/hub/hubtest/hubtest.go 0.00% 200 Missing ⚠️
src/controller/modelsync/controller.go 58.20% 168 Missing ⚠️
...av/model-sync/policy-list/policy-list.component.ts 33.97% 126 Missing and 12 partials ⚠️
src/server/v2.0/handler/modelsync.go 84.21% 48 Missing ⚠️
...create-edit-policy/create-edit-policy.component.ts 80.12% 16 Missing and 16 partials ⚠️
src/controller/modelsync/model.go 68.49% 23 Missing ⚠️
src/pkg/reg/adapter/huggingface/hub/client.go 87.50% 22 Missing ⚠️
src/pkg/reg/adapter/huggingface/pull.go 89.94% 19 Missing ⚠️
src/pkg/reg/adapter/huggingface/locator.go 77.35% 12 Missing ⚠️
src/pkg/modelsync/policy/dao/dao.go 78.43% 11 Missing ⚠️
... and 18 more
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main   #24318      +/-   ##
==========================================
+ Coverage   74.24%   74.86%   +0.62%     
==========================================
  Files        1096     1122      +26     
  Lines      103614   109122    +5508     
  Branches     3079     3194     +115     
==========================================
+ Hits        76926    81699    +4773     
- Misses      26319    27023     +704     
- Partials      369      400      +31     
Flag Coverage Δ
unittests 74.86% <71.47%> (+0.62%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/common/rbac/const.go 46.51% <ø> (ø)
src/controller/registry/controller.go 47.13% <100.00%> (+11.64%) ⬆️
src/jobservice/job/impl/replication/replication.go 63.15% <ø> (ø)
src/jobservice/job/known_jobs.go 0.00% <ø> (ø)
src/pkg/modelsync/policy/manager.go 100.00% <100.00%> (ø)
src/pkg/reg/adapter/huggingface/hub/errors.go 100.00% <100.00%> (ø)
src/pkg/reg/adapter/huggingface/hub/types.go 100.00% <100.00%> (ø)
src/pkg/reg/adapter/huggingface/synth/classify.go 100.00% <100.00%> (ø)
src/pkg/reg/adapter/source.go 100.00% <100.00%> (ø)
src/pkg/reg/manager.go 83.69% <ø> (+16.30%) ⬆️
... and 39 more

... and 8 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

This branch has not been deployed

No deployments
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