fix(create): validate explicit IDs against allowed_prefixes using starts-with matching (#1137)
When creating issues with explicit IDs like `bd create --id hq-cv-test`,
the prefix validation was failing even when `hq-cv` was in `allowed_prefixes`.
Root cause: `ExtractIssuePrefix("hq-cv-test")` returns `"hq"` (not `"hq-cv"`)
because "test" looks like an English word, causing the algorithm to fall back
to the first hyphen. The validation then checked if `"hq"` was in the allowed
list containing `"hq-cv"` - which failed.
The fix adds `ValidateIDPrefixAllowed()` which validates the full ID using
"starts with" matching (the same approach the importer uses successfully).
This correctly handles multi-hyphen prefixes like `hq-cv-` regardless of
what the suffix looks like.
Fixes #1135
Co-authored-by: Steven Syrek <steven.syrek@deepl.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -123,6 +123,49 @@ func ValidatePrefixWithAllowed(requestedPrefix, dbPrefix, allowedPrefixes string
|
||||
return fmt.Errorf("prefix mismatch: database uses '%s' but you specified '%s' (use --force to override)", dbPrefix, requestedPrefix)
|
||||
}
|
||||
|
||||
// ValidateIDPrefixAllowed checks that an issue ID's prefix is allowed.
|
||||
// Unlike ValidatePrefixWithAllowed which takes an extracted prefix, this function
|
||||
// takes the full ID and checks if it starts with any allowed prefix.
|
||||
// This correctly handles multi-hyphen prefixes like "hq-cv-" where the suffix
|
||||
// might look like an English word (e.g., "hq-cv-test").
|
||||
// (GH#1135)
|
||||
//
|
||||
// It matches if:
|
||||
// - force is true
|
||||
// - dbPrefix is empty
|
||||
// - id starts with dbPrefix + "-"
|
||||
// - id starts with any prefix in allowedPrefixes + "-"
|
||||
// Returns an error if none of these conditions are met.
|
||||
func ValidateIDPrefixAllowed(id, dbPrefix, allowedPrefixes string, force bool) error {
|
||||
if force || dbPrefix == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check if ID starts with the database prefix
|
||||
if strings.HasPrefix(id, dbPrefix+"-") {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check if ID starts with any allowed prefix
|
||||
if allowedPrefixes != "" {
|
||||
for _, allowed := range strings.Split(allowedPrefixes, ",") {
|
||||
allowed = strings.TrimSpace(allowed)
|
||||
// Normalize: remove trailing - if present (we add it for matching)
|
||||
allowed = strings.TrimSuffix(allowed, "-")
|
||||
if allowed != "" && strings.HasPrefix(id, allowed+"-") {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build helpful error message
|
||||
if allowedPrefixes != "" {
|
||||
return fmt.Errorf("prefix mismatch: database uses '%s-' (allowed: %s) but ID '%s' doesn't match any allowed prefix (use --force to override)",
|
||||
dbPrefix, allowedPrefixes, id)
|
||||
}
|
||||
return fmt.Errorf("prefix mismatch: database uses '%s-' but ID '%s' doesn't match (use --force to override)", dbPrefix, id)
|
||||
}
|
||||
|
||||
// ValidAgentRoles are the known agent role types for ID pattern validation
|
||||
var ValidAgentRoles = []string{
|
||||
"mayor", // Town-level: gt-mayor
|
||||
|
||||
Reference in New Issue
Block a user