fix(ci): preserve installer compatibility with older releases
This commit is contained in:
5 files changed
+49
-23
No files matched your search
@@ -9,10 +9,17 @@ import (
|
||||
|
||||
func cmdBootstrapAssets(args []string, stdout, stderr io.Writer) int {
|
||||
if len(args) != 1 {
|
||||
fmt.Fprintln(stderr, "felis bootstrap-assets: usage: felis bootstrap-assets crd|game-stack")
|
||||
fmt.Fprintln(stderr, "felis bootstrap-assets: usage: felis bootstrap-assets crd|game-stack|config-keys")
|
||||
return 2
|
||||
}
|
||||
switch args[0] {
|
||||
case "config-keys":
|
||||
// Optional keys the installer may emit; older binaries reject this verb.
|
||||
_, err := fmt.Fprintln(stdout, "velocity.game_version")
|
||||
if err != nil {
|
||||
fmt.Fprintf(stderr, "felis bootstrap-assets: write: %v\n", err)
|
||||
return 1
|
||||
}
|
||||
case "crd":
|
||||
crd, err := felis.MinecraftServerCRD()
|
||||
if err != nil {
|
||||
@@ -32,7 +39,7 @@ func cmdBootstrapAssets(args []string, stdout, stderr io.Writer) int {
|
||||
return 1
|
||||
}
|
||||
default:
|
||||
fmt.Fprintln(stderr, "felis bootstrap-assets: usage: felis bootstrap-assets crd|game-stack")
|
||||
fmt.Fprintln(stderr, "felis bootstrap-assets: usage: felis bootstrap-assets crd|game-stack|config-keys")
|
||||
return 2
|
||||
}
|
||||
return 0
|
||||
|
||||
@@ -5,8 +5,27 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
|
||||
"felis.lolicon.best/internal/config"
|
||||
)
|
||||
|
||||
func TestBootstrapConfigKeys(t *testing.T) {
|
||||
var out, errBuf bytes.Buffer
|
||||
if code := run([]string{"bootstrap-assets", "config-keys"}, &out, &errBuf); code != 0 {
|
||||
t.Fatalf("exit code = %d: %s", code, errBuf.String())
|
||||
}
|
||||
var cfg config.Config
|
||||
meta, err := toml.Decode(strings.TrimSpace(out.String())+` = "26.3"`, &cfg)
|
||||
if err != nil || len(meta.Undecoded()) != 0 {
|
||||
t.Fatalf("advertised config key is unsupported: %v, undecoded: %v", err, meta.Undecoded())
|
||||
}
|
||||
if cfg.Velocity.GameVersion != "26.3" {
|
||||
t.Fatalf("advertised key did not set the game version: %q", cfg.Velocity.GameVersion)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunNoArgsPrintsUsage(t *testing.T) {
|
||||
var out, errBuf bytes.Buffer
|
||||
if code := run(nil, &out, &errBuf); code != 2 {
|
||||
|
||||
+8
-1
@@ -4707,6 +4707,13 @@ offsite_enabled() {
|
||||
# database password.
|
||||
write_felis_toml() {
|
||||
local target="$1" db_addr="$2" deployment="${3:-}" deployment_line="" smtp_block auth_body auth_source_blocks registry_block archive_block offsite_section
|
||||
local config_keys game_version_line=""
|
||||
# main's installer also installs older releases, whose strict TOML parser rejects
|
||||
# newer optional keys. Ask the installed binary rather than guessing from its stamp.
|
||||
config_keys="$("$HOST_BIN" bootstrap-assets config-keys 2>/dev/null || true)"
|
||||
if grep -Fxq 'velocity.game_version' <<<"$config_keys"; then
|
||||
game_version_line="game_version = \"${MC_VERSION:-}\""
|
||||
fi
|
||||
if [ -n "$deployment" ]; then
|
||||
# Starts with the newline that ends the url line, so the pod copy has no blank line there.
|
||||
deployment_line="
|
||||
@@ -4762,7 +4769,7 @@ login_image = "${FELIS_LIMBO_IMAGE}"
|
||||
lobby_image = "${FELIS_LOBBY_IMAGE}"
|
||||
# The public port players connect on; the panel shows it in server addresses.
|
||||
game_port = ${FELIS_GAME_PORT}
|
||||
game_version = "${MC_VERSION:-}"
|
||||
${game_version_line}
|
||||
|
||||
[registry]
|
||||
url = "${REGISTRY_URL}"
|
||||
|
||||
@@ -2042,11 +2042,16 @@ run_write() { # out-file [state-dir] [database-deployment]; under the installer'
|
||||
[ -z "${CAT_FAILS:-}" ] || cat() { head -c 40; return 1; }
|
||||
persisted_smtp_block() { :; }
|
||||
persisted_auth_source_blocks() { :; }
|
||||
felis() {
|
||||
[ "$*" = "bootstrap-assets config-keys" ] || return 2
|
||||
[ "${OLD_CONFIG:-0}" != 1 ] || return 2
|
||||
printf "%s\n" velocity.game_version
|
||||
}
|
||||
. "$FNFILE"
|
||||
FELIS_ROOT_DOMAIN=r.example.com DB_USER=u DB_PASSWORD=p DB_NAME=d MINECRAFT_NS=minecraft \
|
||||
FELIS_EGRESS_MODE=nodeport FELIS_LIMBO_IMAGE=li FELIS_LOBBY_IMAGE=lo FELIS_GAME_PORT=25570 MC_VERSION=26.3 \
|
||||
REGISTRY_URL=registry.felis.svc:5000 BUILD_NS=felis-build FELIS_ARCHIVE_LOCAL_PATH=/a \
|
||||
FELIS_OFFSITE_BUCKET= write_felis_toml "$OUT_TOML" 127.0.0.1:15432 "$DEPLOY"'
|
||||
HOST_BIN=felis FELIS_OFFSITE_BUCKET= write_felis_toml "$OUT_TOML" 127.0.0.1:15432 "$DEPLOY"'
|
||||
}
|
||||
|
||||
run_write "$rdir/out.toml"
|
||||
@@ -2086,6 +2091,13 @@ expect "a re-run carries the scheduled backup retention" 'scheduled_retention =
|
||||
expect "the archive mount stays installer-owned" 'local_path = "/a"' "$out"
|
||||
expect "the panel learns the public game port" 'game_port = 25570' "$out"
|
||||
expect "the panel learns the built login protocol" 'game_version = "26.3"' "$out"
|
||||
(OLD_CONFIG=1 run_write "$rdir/release.toml")
|
||||
release_config="$(cat "$rdir/release.toml")"
|
||||
case "$release_config" in
|
||||
*game_version*) echo "FAIL an older binary must not receive velocity.game_version"; fails=$((fails + 1)) ;;
|
||||
*) echo "PASS an older binary receives no unsupported game-version key" ;;
|
||||
esac
|
||||
expect "an older binary still receives the public game port" 'game_port = 25570' "$release_config"
|
||||
expect "a re-run keeps the off-site bucket, set apart from the next section" '[offsite]
|
||||
endpoint = "https://objects.example"
|
||||
bucket = "felis-offsite"
|
||||
|
||||
@@ -157,25 +157,6 @@ func (k *K8sRunner) awaitPod(ctx context.Context, p JobParams) (*corev1.Pod, err
|
||||
}
|
||||
}
|
||||
|
||||
// podLog reads a finished Pod's log. Follow is off — the Pod has already
|
||||
// terminated, so the log is complete and a follow would merely block until the
|
||||
// stream closed.
|
||||
func (k *K8sRunner) podLog(ctx context.Context, namespace, pod string) (string, error) {
|
||||
stream, err := k.cs.CoreV1().Pods(namespace).GetLogs(pod, &corev1.PodLogOptions{
|
||||
Container: containerName,
|
||||
}).Stream(ctx)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("fileedit: read file job log: %w", err)
|
||||
}
|
||||
defer stream.Close()
|
||||
|
||||
b, err := io.ReadAll(io.LimitReader(stream, maxLogBytes))
|
||||
if err != nil && !errors.Is(err, io.EOF) {
|
||||
return "", fmt.Errorf("fileedit: read file job log: %w", err)
|
||||
}
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
// extractResult finds the marked payload in a Pod log. It scans for the LAST line
|
||||
// carrying ResultPrefix because pods/log returns stdout and stderr MERGED: a Go
|
||||
// runtime warning or a libc message can appear anywhere in the stream, so the
|
||||
|
||||
Reference in new issue
Block a user