fix: Resolve outputs from modules deployed to a different scope - #3910
Open
Jerome Brown (oWretch) wants to merge 1 commit into
Open
fix: Resolve outputs from modules deployed to a different scope#3910Jerome Brown (oWretch) wants to merge 1 commit into
Jerome Brown (oWretch) wants to merge 1 commit into
Conversation
Deployment resources with an explicit `scope` property were registered under their real scope but resolved against the parent deployment scope, so `reference()` on a cross-scope module missed and fell back to a mock. The resulting unresolved value then reached `guid()` as the final argument, where the hash was never finalized and expansion failed with "Hash must be finalized before the hash value is retrieved". `GetDeploymentScope` now parses the explicit `scope` property for management group, subscription, resource group, and tenant components. `GetUnique` now finalizes the hash unconditionally so a non-string final argument cannot throw. Fixes Azure#3909 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Template expansion fails with
Hash must be finalized before the hash value is retrievedwhen an object output from a module deployed to a different scope is used in a string function such asguid().Fixes #3909
Root cause
Two defects, one masking the other.
Cross-scope resource IDs (primary).
DeploymentVisitor.GetDeploymentScoperesolved thesubscriptionId,resourceGroup, andmanagementGroupproperties of a deployment resource but ignored thescopeproperty. For a module withscope: someManagementGroup, the nested deployment was registered under its real scope while the symbol resolved against the parent context scope. The two IDs disagreed, soTemplateContext.TryGetResource()returned false,reference()fell back to a synthetic mock, and.outputs.x.value.idcollapsed to a null value.Hash finalization (secondary).
ExpressionHelpers.GetUniqueonly calledTransformFinalBlockwhen the physically last argument was string-convertible. The unresolved value above landed in the last position, so the hash was never finalized andalgorithm.Hashthrew.Changes
GetDeploymentScopenow parses an explicitscopeproperty viaResourceHelper.ResourceIdComponents, covering management group, subscription, resource group, and tenant scopes. Explicit scope takes precedence over the inherited parent context.GetUniquealways usesTransformBlockin the loop and callsTransformFinalBlock([], 0, 0)once afterwards. SHA-256 output depends only on the concatenated byte stream, not how it is split across blocks, so this is byte-identical for every input that previously succeeded.Both fixes ship together deliberately. Fixing hash finalization alone would turn the exception into silently duplicate
guid()values, because the unresolved argument is skipped rather than reported.Tests
ExpressionHelpersTests.GetUnique_WhenLastArgumentIsNotAString_ShouldNotThrow— null last argument, object last argument, empty args.BicepSymbolicNameTests.ProcessTemplate_WhenObjectOutputPropertyUsedInGuid_ShouldResolveUniqueNameswith fixtureTests.Bicep.6*— a parent template creating a child management group, deploying a custom role definition module and a role assignment module to it withscope:. Asserts distinct resource names and that eachroleDefinitionIdresolves under the child management group.Full
PSRule.Rules.Azure.Testssuite passes (401/401). Also verified end to end against the real-world template that surfaced the issue: 10 role assignments, 10 distinct names, module outputs resolving to real role definition IDs.