Skip to content

Resolve configured registries by name in nebi import - #552

Open
viniciusdc wants to merge 2 commits into
mainfrom
feat/import-registry-name-resolution
Open

Resolve configured registries by name in nebi import#552
viniciusdc wants to merge 2 commits into
mainfrom
feat/import-registry-name-resolution

Conversation

@viniciusdc

@viniciusdc viniciusdc commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Closes #551. The credentials half of that issue is split out into #553, so this closes what the title asks for and nothing else goes quiet with it.

nebi import treated the first path segment of its argument as a DNS hostname, so a registry added with nebi registry add --local could not be named on the import side, while nebi publish --local resolves those same names through the same store.

What resolves now

nebi import myreg:my-env:v1         # the registry named myreg
nebi import myreg:myorg/my-env:v1   # a nested repository through it
nebi import my-env:v1               # the default registry

The target is assembled the way publish assembles its push target, host plus namespace plus repository, so a bundle published as myreg imports back by the same name.

What stays a hostname

Only two shapes resolve: a bare one-segment name, and an explicit <registry>: prefix. Everything else names its own host and is pulled directly with no store lookup.

That line is where the first cut of this got it wrong, twice, and both cases are in the tests now:

  • registry:5000/env:v1, the in-cluster and docker-compose form, was read as alias registry with the port demoted to a namespace segment. The digits after the colon are what separate a port from an alias prefix.
  • registry/my-env:v1 was resolved against the default registry. That is written identically to a namespace-relative path and nothing can tell the two apart, so choosing either breaks the other. Publishing to a single-label host prints registry/team/env:v1, and import could no longer consume publish's own output. A slash now means the first segment is a host.

Picking the host reading for both means nothing that works on main changes meaning. The cost is that myorg/my-env:v1 does not reach the default registry; name the registry for that, myreg:myorg/my-env:v1.

The two-segment form

nebi import myreg:my-env reads as repository myreg, tag my-env, because parseWsRef splits on the last colon. I did not pick a grammar for it. A bare name matching a configured registry is rejected with a message naming the full form:

Error: "myreg" names a configured registry, not a repository; use myreg:<repository>:<tag>

So the ambiguous form fails loudly with the shape that works, rather than guessing. If the shorthand turns out to be worth having, it drops into the same place.

Tests

cmd/nebi/import_ref_test.go covers the split and the resolution against a temp store: named registry, default registry, namespace from the registry record, plain HTTP carried through, unknown name, no default configured, empty reference, and the bare-registry-name rejection. The two shapes above have rows asserting they stay hosts.

The unit tests all feed post-parse strings, so cmd/nebi/bundle_e2e_test.go now imports the published bundle a second and third time by name, once with the alias prefix and once through the default registry. That is the only test that runs the real parseWsRef to StripScheme to splitImportRef chain the command uses.

Also here

The registry lookup and the host/namespace/transport split moved to resolveLocalRegistry and registryTarget in cmd/nebi/client.go, shared with publish --local. The two copies had already drifted: publish reads credentials from the keyring, import does not, which is #553.

`nebi import` treated the first path segment of its argument as a DNS
hostname, so a registry added with `nebi registry add --local` could not
be referred to by name, even though `nebi publish --local` resolves the
same names through the same store.

A reference whose first segment cannot be a host (no dot, no port, not
localhost) is now resolved against the local registries: an explicit
`<name>:<repository>:<tag>` prefix picks one, and no prefix uses the
default. The resolved target is built the way publish builds its push
target, host plus namespace plus repository, so both sides address a
bundle by the same name.

References that already name a host, and references written with an
explicit scheme, keep their exact meaning and never open the local
store, so importing a full reference still works on a machine that has
never run nebi.

A bare name matching a configured registry is rejected rather than
resolved, because `myreg:my-env` parses as repository `myreg`, tag
`my-env`, and silently pulling that from the default registry would be
the wrong thing.

Credentials are unchanged: the pull is still anonymous.
@github-actions

Copy link
Copy Markdown

Docs preview for feat/import-registry-name-resolution (via the nebi-docs Worker):
https://feat-import-registry-name-resolution-nebi-docs.openteams-account.workers.dev

The first cut of the alias rule claimed a reference naming a host never
consults the local store. Two shapes broke that promise, and both are
references that work today.

A dotless host with a port, `registry:5000/env:v1`, is the in-cluster
and docker-compose form. The host test ran only on the part before the
colon, so `registry` was read as an alias and the port became a
namespace segment. With no such alias configured a working command
started failing; with one configured the pull silently went somewhere
else. The digits after the colon are what separate a port from an alias
prefix, so test for them.

A dotless first segment followed by a slash, `registry/my-env:v1`, was
resolved against the default registry. That shape is written exactly
like a namespace-relative path and nothing can tell the two apart, so
picking either one breaks the other. `nebi publish --local` against a
single-label host prints `registry/team/env:v1`, and feeding its own
output back to import no longer worked. A slash now means the first
segment is a host, as it does without this feature. Naming the registry
reaches a nested repository: `myreg:org/my-env:v1`.

That narrows the feature to the two cases that are unambiguous, a bare
one-segment name and an explicit registry prefix, and leaves every other
reference meaning what it means on main.

The registry lookup and the host/namespace/transport split move to
shared helpers so publish and import cannot drift; publish had already
grown a credential lookup import lacks.

Also: an empty reference no longer reports a quoted empty registry name,
and the e2e bundle round-trip now imports by name as well as by full
reference, which is the only test that exercises the parse chain the way
the command does.
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.

nebi import cannot resolve a configured registry by name, unlike publish

1 participant