mirror of
https://github.com/OliveTin/OliveTin
synced 2026-08-23 19:16:33 +00:00
feat: dnsname argument type
Build & Release pipeline / build (push) Canceled after 0s
Buf CI / buf (push) Canceled after 0s
Codestyle checks / codestyle (push) Canceled after 0s
Antora docs / antora (push) Canceled after 0s
Build & Release pipeline / Sign Windows artifacts (SignPath) (push) Canceled after 0s
Antora docs / trigger-docs-publish (push) Canceled after 0s
Build & Release pipeline / build (push) Canceled after 0s
Buf CI / buf (push) Canceled after 0s
Codestyle checks / codestyle (push) Canceled after 0s
Antora docs / antora (push) Canceled after 0s
Build & Release pipeline / Sign Windows artifacts (SignPath) (push) Canceled after 0s
Antora docs / trigger-docs-publish (push) Canceled after 0s
This commit is contained in:
@@ -10,6 +10,7 @@ A full list of argument types are below;
|
||||
| (default) | xref:args/input.adoc[Textbox] | If a `type:` is not set, and `choices:` is empty, then ascii will be used, and a warning will be logged. It is recommended that you set the type explicitly, rather than relying on defaults.
|
||||
| ascii | xref:args/input.adoc[Textbox] | a-z (case insensitive), 0-9, but no spaces or punctuation
|
||||
| ascii_identifier | xref:args/input.adoc[Textbox] | Like a DNS name, a-Z (case insensitive), 0-9, `-`, `.`, and `_`.
|
||||
| dnsname | xref:args/input.adoc[Textbox] | A DNS hostname (RFC 1123). Short names (e.g. `webserver`) and FQDNs (e.g. `webserver.example.com`). Letters/digits/hyphens only, no underscores. Optional trailing dot allowed.
|
||||
| shell_safe_identifier | xref:args/input.adoc[Textbox] | Like an ascii identifier, but also allows `@` and `+`. Useful for shell-safe usernames and email-style identifiers.
|
||||
| ascii_sentence | xref:args/input.adoc[Textbox] | a-z (case insensitive), 0-9, with spaces, `.` and `,`.
|
||||
| unicode_identifier | xref:args/input.adoc[Textbox] | Like an ascii identifier, but allows unicode characters. This is useful for languages that use non-ascii characters, such as Chinese, Japanese, etc.
|
||||
|
||||
@@ -291,7 +291,7 @@ function getInputType (arg) {
|
||||
return 'checkbox'
|
||||
}
|
||||
|
||||
if (arg.type === 'ascii_identifier' || arg.type === 'shell_safe_identifier' || arg.type === 'ascii' || arg.type === 'ascii_sentence') {
|
||||
if (arg.type === 'ascii_identifier' || arg.type === 'dnsname' || arg.type === 'shell_safe_identifier' || arg.type === 'ascii' || arg.type === 'ascii_sentence') {
|
||||
return 'text'
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,9 @@ var (
|
||||
"shell_safe_identifier": `^[a-zA-Z0-9@\.\_\+\-]+$`,
|
||||
"ascii_sentence": `^[a-zA-Z0-9\-\._, ]+$`,
|
||||
}
|
||||
|
||||
dnsNameLabelPattern = regexp.MustCompile(`^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$`)
|
||||
dnsNameAllNumericPattern = regexp.MustCompile(`^[0-9]+$`)
|
||||
)
|
||||
|
||||
// parseExecArray parses all exec arguments in the action.
|
||||
@@ -223,6 +226,8 @@ func TypeSafetyCheck(name string, value string, argumentType string) error {
|
||||
return typeSafetyCheckUrl(value)
|
||||
case "datetime":
|
||||
return typeSafetyCheckDatetime(value)
|
||||
case "dnsname":
|
||||
return typeSafetyCheckDnsName(value)
|
||||
}
|
||||
|
||||
return typeSafetyCheckRegex(name, value, argumentType)
|
||||
@@ -304,6 +309,33 @@ func typeSafetyCheckEmail(value string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// typeSafetyCheckDnsName validates a DNS hostname (RFC 1123 LDH labels).
|
||||
// Accepts short names (e.g. webserver) and FQDNs (e.g. webserver.example.com).
|
||||
// An optional trailing dot is allowed.
|
||||
func typeSafetyCheckDnsName(value string) error {
|
||||
hostname := strings.TrimSuffix(value, ".")
|
||||
if hostname == "" || len(hostname) > 253 {
|
||||
return fmt.Errorf("invalid dnsname length")
|
||||
}
|
||||
|
||||
return typeSafetyCheckDnsNameLabels(strings.Split(hostname, "."))
|
||||
}
|
||||
|
||||
func typeSafetyCheckDnsNameLabels(labels []string) error {
|
||||
for _, label := range labels {
|
||||
if !dnsNameLabelPattern.MatchString(label) {
|
||||
return fmt.Errorf("invalid dnsname label %q", label)
|
||||
}
|
||||
}
|
||||
|
||||
tld := labels[len(labels)-1]
|
||||
if dnsNameAllNumericPattern.MatchString(tld) {
|
||||
return fmt.Errorf("dnsname top-level label must not be all-numeric")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func typeSafetyCheckDatetime(value string) error {
|
||||
_, err := time.Parse("2006-01-02T15:04:05", value)
|
||||
|
||||
|
||||
@@ -812,6 +812,44 @@ func TestTypeSafetyCheckAsciiIdentifier(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTypeSafetyCheckDnsName(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
value string
|
||||
hasError bool
|
||||
}{
|
||||
{"Short name", "webserver", false},
|
||||
{"Localhost", "localhost", false},
|
||||
{"Simple domain", "example.com", false},
|
||||
{"Host with subdomain", "webserver.example.com", false},
|
||||
{"Deep subdomain", "a.b.c.example.co.uk", false},
|
||||
{"Label starting with digit", "1host.example.com", false},
|
||||
{"Trailing dot", "example.com.", false},
|
||||
{"Punycode IDN", "xn--bcher-kva.example", false},
|
||||
{"Underscore", "my_host.example.com", true},
|
||||
{"Space", "example .com", true},
|
||||
{"Leading hyphen label", "-host.example.com", true},
|
||||
{"Trailing hyphen label", "host-.example.com", true},
|
||||
{"Empty label", "example..com", true},
|
||||
{"IP address", "192.168.1.1", true},
|
||||
{"All numeric TLD", "example.123", true},
|
||||
{"All numeric short name", "12345", true},
|
||||
{"Special chars", "exam!ple.com", true},
|
||||
{"Unicode label", "bücher.example.com", true},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := TypeSafetyCheck("host", tt.value, "dnsname")
|
||||
if tt.hasError {
|
||||
assert.NotNil(t, err, "Expected error for value '%s'", tt.value)
|
||||
} else {
|
||||
assert.Nil(t, err, "Expected no error for value '%s', but got: %v", tt.value, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTypeSafetyCheckShellSafeIdentifier(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
Reference in New Issue
Block a user