crucible build parity #14
@@ -1682,10 +1682,12 @@ func validateAutogenConfig(cfg AutogenConfig) []error {
|
|||||||
if strings.TrimSpace(consumer.Mode) == "accessory_visualeffects" && accessoryVisualeffectsConfigConfigured(consumer.AccessoryVisualeffects) {
|
if strings.TrimSpace(consumer.Mode) == "accessory_visualeffects" && accessoryVisualeffectsConfigConfigured(consumer.AccessoryVisualeffects) {
|
||||||
failures = append(failures, validateAccessoryVisualeffectsConfig(fieldPrefix+".accessory_visualeffects", consumer.AccessoryVisualeffects)...)
|
failures = append(failures, validateAccessoryVisualeffectsConfig(fieldPrefix+".accessory_visualeffects", consumer.AccessoryVisualeffects)...)
|
||||||
}
|
}
|
||||||
// A manifest_file consumer reads a pre-resolved local manifest, so the
|
// A manifest_file consumer reads a pre-resolved local manifest, and a
|
||||||
// released-source fields (root/include/derive/manifest) are never read
|
// cdn_channel consumer resolves entirely from Source.* at runtime, so
|
||||||
|
// neither reads the released-source fields (root/include/derive/manifest)
|
||||||
// at build time — don't require them. See resolveAutogenConsumerManifest.
|
// at build time — don't require them. See resolveAutogenConsumerManifest.
|
||||||
if strings.TrimSpace(consumer.ManifestFile) == "" {
|
if strings.TrimSpace(consumer.ManifestFile) == "" &&
|
||||||
|
strings.TrimSpace(consumer.Source.Kind) != "cdn_channel" {
|
||||||
if strings.TrimSpace(consumer.Root) == "" {
|
if strings.TrimSpace(consumer.Root) == "" {
|
||||||
failures = append(failures, fmt.Errorf("%s.root is required", fieldPrefix))
|
failures = append(failures, fmt.Errorf("%s.root is required", fieldPrefix))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1425,6 +1425,51 @@ func TestValidateLayoutRejectsInvalidAccessoryVisualeffectsNamingConfig(t *testi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestValidateLayoutAcceptsCDNChannelConsumerWithoutReleasedSourceFields(t *testing.T) {
|
||||||
|
// cdn_channel consumers resolve entirely from Source.* at runtime; they must
|
||||||
|
// not be required to supply root/include/derive/manifest fields.
|
||||||
|
root := t.TempDir()
|
||||||
|
mkdirAll(t, filepath.Join(root, "src"))
|
||||||
|
mkdirAll(t, filepath.Join(root, "build"))
|
||||||
|
|
||||||
|
proj := &Project{
|
||||||
|
Root: root,
|
||||||
|
Config: Config{
|
||||||
|
Module: ModuleConfig{Name: "Test", ResRef: "test"},
|
||||||
|
Paths: PathConfig{Source: "src", Build: "build"},
|
||||||
|
Autogen: AutogenConfig{
|
||||||
|
Consumers: []AutogenConsumerConfig{
|
||||||
|
{
|
||||||
|
ID: "accessory_visualeffects",
|
||||||
|
Producer: "accessory_visualeffects",
|
||||||
|
Dataset: "visualeffects",
|
||||||
|
Mode: "accessory_visualeffects",
|
||||||
|
Optional: true,
|
||||||
|
AccessoryVisualeffects: AccessoryVisualeffectsConfig{
|
||||||
|
Groups: map[string]AccessoryVisualeffectGroupConfig{
|
||||||
|
"head_accessories": {Prefix: "head_acc_"},
|
||||||
|
"chest_accessories": {Prefix: "chest_acc_"},
|
||||||
|
"head_decorations": {Prefix: "head_dec_"},
|
||||||
|
"head_features": {Prefix: "head_feat_"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Source: AutogenSourceConfig{
|
||||||
|
Kind: "cdn_channel",
|
||||||
|
ChannelsPath: "releases/haks/channels.json",
|
||||||
|
ManifestPath: "releases/haks/{tag}/vfxs.yml",
|
||||||
|
},
|
||||||
|
// Intentionally omitted: Root, Include, Derive, Manifest
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := proj.ValidateLayout(); err != nil {
|
||||||
|
t.Fatalf("cdn_channel consumer should pass ValidateLayout without released-source fields, got: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestLoadRejectsLegacyAccessoryVisualeffectsNamingFields(t *testing.T) {
|
func TestLoadRejectsLegacyAccessoryVisualeffectsNamingFields(t *testing.T) {
|
||||||
root := t.TempDir()
|
root := t.TempDir()
|
||||||
writeProjectFile(t, filepath.Join(root, ConfigFile), `
|
writeProjectFile(t, filepath.Join(root, ConfigFile), `
|
||||||
|
|||||||
@@ -189,6 +189,10 @@ func autogenConsumerManagedLockKeyMatcher(consumer project.AutogenConsumerConfig
|
|||||||
prefix := dataset + ":"
|
prefix := dataset + ":"
|
||||||
// Build the group set from the resolved policy so consumers that omit
|
// Build the group set from the resolved policy so consumers that omit
|
||||||
// AccessoryVisualeffects.Groups still match the four default group names.
|
// AccessoryVisualeffects.Groups still match the four default group names.
|
||||||
|
// NOTE: this matcher assumes the default folder_name+preserve group
|
||||||
|
// representation. Keys produced under case:lower or
|
||||||
|
// group_token_source:prefix would not match and would escape pruning;
|
||||||
|
// no production config uses those combinations.
|
||||||
policy := resolveAccessoryVisualeffectsPolicy(consumer, nil)
|
policy := resolveAccessoryVisualeffectsPolicy(consumer, nil)
|
||||||
groups := make(map[string]struct{}, len(policy.Groups))
|
groups := make(map[string]struct{}, len(policy.Groups))
|
||||||
for group := range policy.Groups {
|
for group := range policy.Groups {
|
||||||
@@ -322,7 +326,7 @@ func resolveCDNChannelManifest(p *project.Project, consumer project.AutogenConsu
|
|||||||
channel = deriveAssetChannel(p.Root)
|
channel = deriveAssetChannel(p.Root)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. CDN base: env override, then config literal, then baked default.
|
// 3. CDN base: baked default, then env override, then config literal (most specific wins).
|
||||||
cdnBase := defaultBunnyCDNBase
|
cdnBase := defaultBunnyCDNBase
|
||||||
if envName := strings.TrimSpace(src.CDNBaseEnv); envName != "" {
|
if envName := strings.TrimSpace(src.CDNBaseEnv); envName != "" {
|
||||||
if v := strings.TrimSpace(os.Getenv(envName)); v != "" {
|
if v := strings.TrimSpace(os.Getenv(envName)); v != "" {
|
||||||
|
|||||||
@@ -159,6 +159,18 @@ func TestResolveCDNChannelHardFail(t *testing.T) {
|
|||||||
t.Fatalf("want HARD fail, got %v", err)
|
t.Fatalf("want HARD fail, got %v", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("malformed vfxs.yml: syntactically broken YAML", func(t *testing.T) {
|
||||||
|
srv := cdnServer(t, map[string]string{
|
||||||
|
"/releases/haks/channels.json": `{"current":"v1"}`,
|
||||||
|
"/releases/haks/v1/vfxs.yml": "assets:\n - path: [unterminated",
|
||||||
|
})
|
||||||
|
t.Setenv("BUNNY_CDN_BASE", srv.URL)
|
||||||
|
_, err := resolveCDNChannelManifest(testProject(root), c, c.Source, nil)
|
||||||
|
if err == nil || errorIsUnavailable(err) {
|
||||||
|
t.Fatalf("want HARD fail on broken YAML, got %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestResolveCDNChannelOfflineOverride(t *testing.T) {
|
func TestResolveCDNChannelOfflineOverride(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user