Skip to content

Support for local filesystem-based registry aliases#19452

Open
SimonWahlin wants to merge 11 commits into
Azure:mainfrom
SimonWahlin:OciArtifactEmulation
Open

Support for local filesystem-based registry aliases#19452
SimonWahlin wants to merge 11 commits into
Azure:mainfrom
SimonWahlin:OciArtifactEmulation

Conversation

@SimonWahlin
Copy link
Copy Markdown
Collaborator

@SimonWahlin SimonWahlin commented Apr 16, 2026

Description

When developing modules that are published to a module registry, this feature will add the ability to test existing templates by redirecting a br/alias to a filesystem path.

Fixes #17096

Example Usage

Having an existing template that deploys a module using the following code:

main.bicep

module myModule 'br/MyRegistry:mymodule:1.0.0' = {}

output mainOutput string = myModule.outputs.moduleOutput

I want to make changes to mymodule and need to validate them before publishing version 1.0.1 to my registry. I update mymodule and save it as mymodule.bicep in a subfolder named bicepmodules.

bicepmodules/mymodule.bicep

output moduleOutput string = 'Hello from myModule version 1.0.1'

To make my template (main.bicep) use the updated module on my filesystem instead of the one from my container registry, I update my bicepconfig.json to the following:

bicepconfig.json

{
  "moduleAliases": {
    "br": {
      "MyRegistry": {
        "fileSystem": "bicepModules"
      }
    }
  }
}

This is using the new property "filesystem" instead of "registry" which will emulate having a read-only OCI registry.

I have intentionally not exposed a new prefix for moduleAliases to be able to deploy existing templates that are using the br/ prefix.

Checklist

Microsoft Reviewers: Open in CodeFlow

Copilot AI review requested due to automatic review settings April 16, 2026 19:47
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds support for filesystem-backed br/<alias>: module aliases so developers can redirect OCI module references to local .bicep files during iteration (Bicep.Core registry/config + tests/baselines).

Changes:

  • Extend moduleAliases.br.<alias> to support a fileSystem target (mutually exclusive with registry).
  • Add an emulated OCI artifact reference type and a registry implementation to load modules directly from disk without restore/cache.
  • Update diagnostics/tests and refresh the Registry_LF baseline to include an emulated registry alias scenario.

Reviewed changes

Copilot reviewed 22 out of 22 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/Bicep.Core/Registry/OciArtifactRegistry.cs Routes br/<alias>: parsing to a filesystem-emulated reference when the alias has fileSystem.
src/Bicep.Core/Registry/Oci/OciArtifactReferenceFacts.cs Adds internal scheme constant for emulated OCI references.
src/Bicep.Core/Registry/Oci/OciArtifactEmulatedReference.cs New artifact reference type resolving br/<alias>: modules to local .bicep files.
src/Bicep.Core/Registry/FileSystemModuleRegistry.cs New registry for br-fs references used during restore/check operations.
src/Bicep.Core/Registry/DefaultArtifactRegistryProvider.cs Registers the new registry and wires IFileExplorer into OciArtifactRegistry.
src/Bicep.Core/Modules/ModuleReferenceSchemes.cs Exposes the internal emulated scheme.
src/Bicep.Core/Diagnostics/DiagnosticBuilder.cs Updates alias diagnostics and hides the internal scheme from “unknown scheme” messages.
src/Bicep.Core/Configuration/ModuleAliasesConfiguration.cs Adds fileSystem to OCI alias config and validates mutual exclusivity.
src/Bicep.Core.UnitTests/Utils/OciRegistryHelper.cs Updates test helper for new OciArtifactRegistry constructor signature.
src/Bicep.Core.UnitTests/Registry/OciArtifactEmulatedReferenceTests.cs New unit tests for parsing/emulated reference behavior and alias validation.
src/Bicep.Core.UnitTests/Modules/OciArtifactModuleReferenceTests.cs Updates expected diagnostics for alias validation changes.
src/Bicep.Core.Samples/Files/baselines/Registry_LF/* Baseline updates to cover filesystem-based alias usage.
Comments suppressed due to low confidence (1)

src/Bicep.Core/Configuration/ModuleAliasesConfiguration.cs:118

  • TryGetOciArtifactModuleAlias enforces registry XOR fileSystem, but it allows modulePath to be set alongside fileSystem. In the current implementation, modulePath is ignored for filesystem-based aliases, which makes that configuration misleading. Consider either (a) rejecting fileSystem + modulePath with a diagnostic, or (b) applying modulePath as an additional subdirectory when resolving modulePath.bicep so behavior stays aligned with how modulePath works for registry aliases.
            if (alias.Registry is not null && alias.FileSystem is not null)
            {
                return new(x => x.InvalidOciArtifactModuleAliasRegistryAndFileSystemSetTogether(aliasName, configFileUri));
            }

            if (alias.Registry is null && alias.FileSystem is null)
            {
                return new(x => x.InvalidOciArtifactModuleAliasRegistryNullOrUndefined(aliasName, configFileUri));
            }

            return new(alias);

Comment thread src/Bicep.Core/Registry/Oci/OciArtifactEmulatedReference.cs
Comment thread src/Bicep.Core/Registry/FileSystemModuleRegistry.cs Outdated
Comment thread src/Bicep.Core/Registry/Oci/OciArtifactEmulatedReference.cs Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 24 out of 24 changed files in this pull request and generated 4 comments.

Comment thread src/Bicep.Core/Registry/Oci/OciArtifactEmulatedReference.cs Outdated
Comment thread src/Bicep.Core/Registry/Oci/OciArtifactEmulatedReference.cs
Comment thread src/Bicep.Core/Registry/Oci/OciArtifactEmulatedReference.cs
Comment thread src/Bicep.Core.IntegrationTests/RegistryTests.cs
@anthony-c-martin
Copy link
Copy Markdown
Member

anthony-c-martin commented May 11, 2026

Looking at this bicepconfig example, it's using the br module alias (BR for Bicep Registry). Shouldn't we instead use a different prefix (e.g. local) to indicate this isn't a registry?

{
  "moduleAliases": {
    "br": {
      "MyRegistry": {
        "fileSystem": "bicepModules"
      }
    }
  }
}

To me it's confusing that the following would map to the file system:

module myModule 'br/MyRegistry:mymodule:1.0.0' = {}

Whereas the following is clearer:

module myModule 'local/myAlias:mymodule' = {}

@SimonWahlin
Copy link
Copy Markdown
Collaborator Author

The purpose of this PR is to be able to locally emulate an ACR to shorten the dev-cycle of modules.

Imagine I have a prod ACR where all company modules are hosted. They are of course immutable and won't be changed once published. I have a module (mymodule@1.0.0) that I need to update and release in version 1.1.0. To make sure of the quality of my new module version, I want to deploy a few of my existing templates using this new version of my module. What I would do today is create a personal ACR (or a personal namespace/path in a dev-ACR without immutability), publish my module there for QA and change the module alias to point to my personal ACR. Everyone involved in QA of my module would either have to have access to my personal ACR or publish the module to their own personal ACR. This quickly becomes complicated if the module I'm testing also depends on other modules in the same registry, then they have to be published to my personal ACR as well.

With this feature, anyone can check out my PR to the modules repo, point/redirect the module alias to the local repository folder and deploy any template without modification and without worrying about which modules that has to be available as well. That's why I've chosen to call the class OciArtifactEmulatedReference since the whole purpose is to be able to emulate an ACR registry. The EmulatedReference also uses the same br prefix to be able to deploy existing templates without modifications.

I don't mind implementing a local or fs alias as well, I think that might be useful instead of using paths like '../../../../../Modules/MyModule.bicep' which is all too common (and a bit too error prone in my opinon).

@shenglol
Copy link
Copy Markdown
Contributor

shenglol commented May 15, 2026

Looking at this bicepconfig example, it's using the br module alias (BR for Bicep Registry). Shouldn't we instead use a different prefix (e.g. local) to indicate this isn't a registry?

{
  "moduleAliases": {
    "br": {
      "MyRegistry": {
        "fileSystem": "bicepModules"
      }
    }
  }
}

To me it's confusing that the following would map to the file system:

module myModule 'br/MyRegistry:mymodule:1.0.0' = {}

Whereas the following is clearer:

module myModule 'local/myAlias:mymodule' = {}

I asked the same question earlier, before @SimonWahlin sent the PR. I think he made a good point that requiring the author to change the module path scheme in order to test a new module version would not be ideal.

That said, after reading through the samples and test code, I do feel that overloading the existing moduleAliases section could lead to confusion. I have an alternative idea: could we introduce a moduleAliasesMock section that, if present, would supersede moduleAliases? For example:

 {
   "moduleAliasesMock": { 
     "br": {
       "MyRegistry": {
         "fileSystem": "bicepModules"
       }
     }
   }
}

@SimonWahlin @anthony-c-martin What do you think?

@SimonWahlin
Copy link
Copy Markdown
Collaborator Author

I like the idea of calling it a moduleAliasesMock, that would clear up risk of confusion and also be very clear about the purpose of the feature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support for local filesystem-based registry aliases

4 participants