-
Notifications
You must be signed in to change notification settings - Fork 810
Description
Goals
This is intended to provide an approximation of the Bicep registry experience IF we chose OCI Artifacts as the package manager and implement the integration. The existence of this issue DOES NOT indicate that OCI was selected as the implementation of the Bicep Registry. (See #2128 for details about other candidates.)
Gallery Experience
TBD
CLI
bicep build
Since Bicep modules can contain references to modules published to an artifact registry, the artifact contents may not exist on the local system. If the Bicep file contains references to external modules, bicep build pulls the referenced artifacts before type checking and code generation and stores them on the local file system. (In the compiler pipeline, the pull step occurs after parsing but before type checking is done.)
By default, the artifact cache is located at %USERPROFILE%\.bicep\artifacts on Windowsand ~/.bicep/artifacts on Linux and Mac. The location can be customized via the BICEP_ARTIFACTS environment variable. (If the language server and CLI tools are pointed to different artifact cache paths, they will each download a separate copy of each referenced artifact.)
Note: This is a custom mechanism that we will have to build ourselves. It will have to account for possibility of concurrent pull operations.
Open Question: Do we need to expose a setting for the artifact cache path in
bicepconfig.jsonlike NuGet does?
bicep pull
In certain usecases (Docker and some CI systems), the restore and build operations need to be separated. This can be accomplished as follows:
bicep pullbicep build --no-pull main.bicep
Open Question: What verb do we use for this command? (NPM and Go use
install. .Net/MSBuild userestore. Docker/OCI usepull.)
Open Question: Docker has been aggressively throttling anonymous artifact/image pull requests since late 2020. Do we need to support authentication even for public registries as a result.
Reference module from an artifact
To reference a module from a package, the opens a new or existing Bicep file in VS code and types one or more declarations like the following:
module mod 'majastrzoci.azurecr.io/bicep/modules/test:0.1-alpha' = {
...
}OCI does not have a concept of a package feed like NuGet does. Instead, references are made directly via a URI. The URI has the following components:
majastrzoci.azurecr.io- URI of the registrybicep/modules/test- Identifies the repository. A repository is a collection of artifacts with the same name but different tags.0.1-alpha- Identifies the artifact tag, which is similar to a package version in NuGet. (However, the same image/artifact content may have multiple tags or may be untagged.)
See https://docs.microsoft.com/en-us/azure/container-registry/container-registry-concepts for more details.
Open Question: This example covers the most minimal syntax we could have. The syntax proposals for referencing external modules are tracked in #3186.
OCI also allows referencing artifacts by their SHA256 digest. The syntax for this would look like the following:
module mod 'majastrzoci.azurecr.io/bicep/modules/test@sha256:07601524fed07e648d40018070ea8927acb9d2bc695e9ebd3566ac113b98dda9' = {
...
}Open Question: Should we even support references by digest? In otherwords, should we allow references to untagged artifacts?
Open Question: Even if we decide to support digest references, do we need to offer completions for digests?
No mechanism exists to enumerate all possible registry URIs, which means we will NOT be able to provide completions for the registry URI portion of the module type string. Once the registry URI is typed in (and auth is setup), we will be able to provide completions for the image name and tags.
Open Question: The lack of full completion experience suggests that we should develop a custom mechanism to configure the list of registries separately from the .bicep file and reference them by alias.
If the current module has any external module references, the language server queues up a pull action in the background. The background process will check the package cache for the artifact name and tag. If missing, the package will be downloaded from the registry.
The background pull operation does not happen instantly. Until the artifact is in the local artifact cache, accurate type information is not available:
- The language server falls back to the widest possible type for the given context. (
anyorobject) - A warning is shown on the module ref indicating that the artifact is not yet available.
- Property name and property access completions involving this particular module are unavailable.
- The language server remains otherwise functional.
If/when restore fails:
- An error is shown on the module ref explaing the type of failure.
- The language server remains otherwise functional.
Once the background pull operation is finished successfully, the language server recompiles the module to make use of the downloaded type info (we can reuse the parse tree). Property name and property access completions are now available for the module.
Open Question: Where do we expose the OCI logs? In VS code "Output" pane under "Bicep Package Manager"?
Setup private registry
Several registries support OCI artifacts. A good list is available at https://oras.land/implementors/. An Azure Container Registry can be easily created via the Azure Portal or a .bicep file.
Open Question: How will the auth work for registries? Is there a standard extensibility model or do we need to custom build it?
Setup local registry
Using a local docker installation, you can run the registry image:
docker run -it --rm -p 5000:5000 registryThis makes a non-persistent registry available at localhost:5000.
Create package
OCI artifacts are either pushed from local file system to a registry or pulled from the registry down to the local file system. (It is also possible to transfer artifacts between registries, but it's less relevant here.) There is no "package" concept that is a single-file representation of all the layers in an OCI artifact that would be equivalent to a .nupkg in NuGet or similar in other package managers.
Push artifact to registry
An artifact can be pushed to the registry via the bicep push <file> command. The command performs the following operations:
- Pull referenced artifacts to populate the local cache (can opt-out with
--no-pull) - Validate module (including configured linter rules)
- Prepare artifact content for publishing in a temp location
- Push to the registry
The artifact contents will be as follows:
- The main module.
- The local modules referenced by the main module.
- External modules referenced by the main and local modules become dependencies of the artifact.
A more detailed discussion about package contents is tracked in #3266. The discussion of module metadata lives in #3187.
Open Question: How do we express the dependency on other artifacts? Do we implement our own custom metadata to annotate dependencies or do we lean into the layering capabilities of OCI? (The former has implications to artifact pull latency.)
Open Question: OCI is completely generic and requires only artifact name and tag. What other metadata do we need?
Open Question: How to encode min/max Bicep version in the artifact? Can we add our own custom annotations to the manifest?
Sign artifact
TBD