@@ -126,7 +126,8 @@ func RenderComponents(env *azldev.Env, options *RenderOptions) ([]*RenderResult,
126126 // Check early to avoid wasting work on all three phases.
127127 if options .ComponentFilter .IncludeAllComponents && ! options .Force {
128128 return nil , errors .New (
129- "rendering all components (-a) requires --force to enable cleanup of stale output directories" )
129+ "rendering all components (-a) requires --force to enable cleanup of stale output directories" +
130+ " (auto-set when rendered-specs-dir is configured)" )
130131 }
131132
132133 resolver := components .NewResolver (env )
@@ -208,21 +209,31 @@ func sortRenderResults(results []*RenderResult) {
208209 })
209210}
210211
211- // checkRenderErrors counts error results and returns an error if FailOnError is set.
212+ // checkRenderErrors counts error and cancelled results and returns an error if FailOnError is set.
212213func checkRenderErrors (results []* RenderResult , failOnError bool ) error {
213- errCount := 0
214+ var errCount , cancelledCount int
214215
215216 for _ , result := range results {
216- if result != nil && result .Status == renderStatusError {
217+ if result == nil {
218+ continue
219+ }
220+
221+ switch result .Status {
222+ case renderStatusError :
217223 errCount ++
224+ case renderStatusCancelled :
225+ cancelledCount ++
218226 }
219227 }
220228
221- if errCount > 0 {
222- slog .Error ("Some components failed to render" , "errorCount" , errCount )
229+ failCount := errCount + cancelledCount
230+
231+ if failCount > 0 {
232+ slog .Error ("Some components failed to render" ,
233+ "errorCount" , errCount , "cancelledCount" , cancelledCount )
223234
224235 if failOnError {
225- return fmt .Errorf ("%d component(s) failed to render" , errCount )
236+ return fmt .Errorf ("%d component(s) failed to render" , failCount )
226237 }
227238 }
228239
@@ -323,12 +334,7 @@ func prepWithSemaphore(
323334 compOutputDir := filepath .Join (outputDir , componentName )
324335
325336 // Validate component name before any filesystem work to prevent path traversal.
326- // This mirrors validateComponentInput in mockprocessor.go but runs earlier
327- // (before staging dir creation and RemoveAll calls).
328- if componentName == "" || componentName == "." ||
329- strings .ContainsAny (componentName , "/\\ " ) ||
330- strings .Contains (componentName , ".." ) ||
331- strings .ContainsRune (componentName , 0 ) {
337+ if ! sources .IsSimpleName (componentName ) {
332338 return prepResult {index : index , result : & RenderResult {
333339 Component : componentName ,
334340 OutputDir : "(invalid)" ,
@@ -620,7 +626,7 @@ func finishComponentRender(
620626 mockResult , hasMockResult := mockResultMap [componentName ]
621627 if ! hasMockResult {
622628 return fmt .Errorf (
623- "no mock result for %#q (batch processing may have failed )" , componentName )
629+ "no mock result for %#q (batch mock processing failed; see earlier errors )" , componentName )
624630 }
625631
626632 if mockResult .Error != nil {
@@ -759,7 +765,15 @@ func findSpecFile(fs opctx.FS, dir, componentName string) (string, error) {
759765
760766 for _ , entry := range entries {
761767 if ! entry .IsDir () && filepath .Ext (entry .Name ()) == ".spec" {
762- return filepath .Join (dir , entry .Name ()), nil
768+ foundPath := filepath .Join (dir , entry .Name ())
769+
770+ slog .Warn ("Spec filename does not match component name; using fallback" ,
771+ "component" , componentName ,
772+ "expected" , componentName + ".spec" ,
773+ "found" , entry .Name (),
774+ )
775+
776+ return foundPath , nil
763777 }
764778 }
765779
0 commit comments