Skip to content
10 changes: 8 additions & 2 deletions pkg/api/ws_dispatcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -585,8 +585,14 @@ func TestWebSocketRunJobStartsMethodTimeoutAtExecution(t *testing.T) {
tt.method,
)),
}
time.Sleep(25 * time.Millisecond)
require.Error(t, enqueuedCtx.Err(), "pre-existing enqueue-time context should be expired")
// Waited for rather than slept past: a deadline is recorded by a timer
// goroutine, so under load the wall clock passes the deadline well
// before anything runs to set the error.
select {
case <-enqueuedCtx.Done():
case <-time.After(5 * time.Second):
t.Fatal("pre-existing enqueue-time context should be expired")
}

beforeRun := time.Now()
d.runJob(job)
Expand Down
6 changes: 4 additions & 2 deletions pkg/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func SetupFlags() *Flags {
"send method and params to API and print response",
),
Version: flag.Bool(
"version",
config.VersionFlagName,
false,
"print version and exit",
),
Expand Down Expand Up @@ -166,7 +166,9 @@ func (f *Flags) Pre(pl platforms.Platform) {
flag.Parse()

if *f.Version {
_, _ = fmt.Printf("Zaparoo v%s (%s)\n", config.AppVersion, pl.ID())
// config.VersionLine, not a literal: the self-update probe compares a
// staged binary's output against it, so the two must not drift.
_, _ = fmt.Printf("%s\n", config.VersionLine(config.AppVersion, pl.ID()))
os.Exit(0)
}
}
Expand Down
22 changes: 22 additions & 0 deletions pkg/config/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package config

import (
"fmt"
"strings"
"time"
)
Expand Down Expand Up @@ -56,4 +57,25 @@ const (
CacheDir = "cache"
LogUploadURL = "https://logs.zaparoo.org/"
MinFreeDiskBytes = 500 * 1024 * 1024 // 500 MB

// VersionFlagName is the flag that prints VersionLine and exits. The
// self-update probe passes it to a binary it has just downloaded, so the
// name is part of the same frozen contract as the line itself.
VersionFlagName = "version"
)

// VersionLine is the line the version flag prints, and the line the self-update
// probe looks for in a staged binary's output.
//
// It is a compatibility surface between releases, not a cosmetic string. The
// probe runs in the binary that is already installed and checks what the
// incoming one prints, so it is always the *older* build that decides whether a
// newer release is acceptable. Changing this text would make every device
// already in the field reject the release that changed it, and every release
// after that, with no way to fix it from the new release's side. Both the
// producer and the probe read it from here so they cannot drift, and the probe
// matches this as one line of output rather than the whole stream so that
// adding another line elsewhere stays harmless.
func VersionLine(version, platformID string) string {
return fmt.Sprintf("Zaparoo v%s (%s)", version, platformID)
}
50 changes: 50 additions & 0 deletions pkg/config/app_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Zaparoo Core
// Copyright (c) 2026 The Zaparoo Project Contributors.
// SPDX-License-Identifier: GPL-3.0-or-later
//
// This file is part of Zaparoo Core.
//
// Zaparoo Core is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Zaparoo Core is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Zaparoo Core. If not, see <http://www.gnu.org/licenses/>.

package config

import (
"testing"

"github.com/stretchr/testify/assert"
)

// TestVersionLine_IsFrozen is a tripwire, not a restatement of the code. The
// self-update probe runs in the binary a device already has installed and
// compares what a freshly downloaded one prints against this text, so the older
// build is always the one judging the newer. Editing the format would make
// every device in the field refuse the release that changed it and every
// release after it, unrecoverably from the new release's side.
//
// If this test fails, the change is a compatibility break, not a typo fix.
func TestVersionLine_IsFrozen(t *testing.T) {
t.Parallel()

assert.Equal(t, "Zaparoo v2.11.0 (mister)", VersionLine("2.11.0", "mister"))
assert.Equal(t, "Zaparoo v2.11.0-beta4 (linux)", VersionLine("2.11.0-beta4", "linux"))
}

// TestVersionFlagName_IsFrozen guards the other half of the same contract: the
// probe invokes a downloaded binary with this flag, so an installed build can
// only ask a future one for its version by the name it knows today.
func TestVersionFlagName_IsFrozen(t *testing.T) {
t.Parallel()

assert.Equal(t, "version", VersionFlagName)
}
Loading
Loading