fix heartbeat validation rejecting git-describe version strings
the version regex only allowed [a-zA-Z0-9.] in semver suffixes, which rejected hyphens from git-describe output (e.g. 0.1.0-5-gabcdef0). this caused every heartbeat to fail validation, preventing last_seen_at from updating, which led to agent status showing "warning" and eventual channel disconnect after 360s. also accept bare git SHAs and short identifiers like "dev".
This commit is contained in:
parent
c5d8d73a0c
commit
f2cd3488ee
2 changed files with 52 additions and 14 deletions
|
|
@ -191,28 +191,29 @@ defmodule Towerops.Agent.Validator do
|
|||
{:error, {:decode_error, "Invalid protobuf message format"}}
|
||||
end
|
||||
|
||||
# Validate version format - accepts either semantic version or RFC 3339 timestamp
|
||||
# Empty string allowed for backward compat
|
||||
# Validate version format - accepts semver, RFC 3339 timestamp, git describe,
|
||||
# git short SHA, or "dev". Empty string allowed for backward compat.
|
||||
defp validate_version(""), do: :ok
|
||||
|
||||
defp validate_version(version) when is_binary(version) do
|
||||
cond do
|
||||
# Semantic version format (backward compatibility with old agents)
|
||||
# Pattern: X.Y.Z or X.Y.Z-suffix
|
||||
String.match?(version, ~r/^\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?$/) ->
|
||||
if String.length(version) <= @max_short_string_length,
|
||||
do: :ok,
|
||||
else: {:error, {:invalid_version, "Version too long"}}
|
||||
String.length(version) > @max_short_string_length ->
|
||||
{:error, {:invalid_version, "Version too long"}}
|
||||
|
||||
# RFC 3339 timestamp format (new agents with compile timestamp)
|
||||
# Pattern: YYYY-MM-DDTHH:MM:SSZ
|
||||
# Semantic version with git-describe suffixes (e.g., 1.2.3, 1.2.3-rc.1, 1.2.3-5-gabcdef0)
|
||||
String.match?(version, ~r/^\d+\.\d+\.\d+(-[a-zA-Z0-9.\-]+)?$/) ->
|
||||
:ok
|
||||
|
||||
# RFC 3339 timestamp format (e.g., 2026-02-11T17:00:00Z)
|
||||
String.match?(version, ~r/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/) ->
|
||||
if String.length(version) <= @max_short_string_length,
|
||||
do: :ok,
|
||||
else: {:error, {:invalid_version, "Version too long"}}
|
||||
:ok
|
||||
|
||||
# Git short SHA (7-40 hex chars) or short identifier like "dev"
|
||||
String.match?(version, ~r/^[a-zA-Z0-9]{1,40}$/) ->
|
||||
:ok
|
||||
|
||||
true ->
|
||||
{:error, {:invalid_version, "Version must be semver format (e.g., 1.2.3) or RFC 3339 timestamp"}}
|
||||
{:error, {:invalid_version, "Version must be semver, RFC 3339 timestamp, or short identifier"}}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -535,6 +535,43 @@ defmodule Towerops.Agent.ValidatorTest do
|
|||
assert {:ok, _} = Validator.validate_heartbeat(binary)
|
||||
end
|
||||
|
||||
test "accepts git-describe version with commit count and SHA" do
|
||||
heartbeat = %AgentHeartbeat{
|
||||
version: "0.1.0-5-gabcdef0",
|
||||
hostname: "agent01",
|
||||
uptime_seconds: 100,
|
||||
ip_address: ""
|
||||
}
|
||||
|
||||
binary = AgentHeartbeat.encode(heartbeat)
|
||||
assert {:ok, validated} = Validator.validate_heartbeat(binary)
|
||||
assert validated.version == "0.1.0-5-gabcdef0"
|
||||
end
|
||||
|
||||
test "accepts bare git short SHA as version" do
|
||||
heartbeat = %AgentHeartbeat{
|
||||
version: "abcdef0",
|
||||
hostname: "agent01",
|
||||
uptime_seconds: 100,
|
||||
ip_address: ""
|
||||
}
|
||||
|
||||
binary = AgentHeartbeat.encode(heartbeat)
|
||||
assert {:ok, _} = Validator.validate_heartbeat(binary)
|
||||
end
|
||||
|
||||
test "accepts 'dev' as version" do
|
||||
heartbeat = %AgentHeartbeat{
|
||||
version: "dev",
|
||||
hostname: "agent01",
|
||||
uptime_seconds: 100,
|
||||
ip_address: ""
|
||||
}
|
||||
|
||||
binary = AgentHeartbeat.encode(heartbeat)
|
||||
assert {:ok, _} = Validator.validate_heartbeat(binary)
|
||||
end
|
||||
|
||||
test "accepts RFC 3339 timestamp version format" do
|
||||
heartbeat = %AgentHeartbeat{
|
||||
version: "2025-02-09T15:30:45Z",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue