ci: 加 -race、staticcheck、govulncheck、shellcheck 与真 PostgreSQL 集成测试门禁,release 复用 ci 门禁
This commit is contained in:
8 files changed
+130
-58
No files matched your search
@@ -14,10 +14,14 @@
|
|||||||
# PR is what asks for the answer.
|
# PR is what asks for the answer.
|
||||||
name: ci
|
name: ci
|
||||||
|
|
||||||
|
#
|
||||||
|
# release.yml calls this workflow (workflow_call) before it builds anything, so a tag passes
|
||||||
|
# exactly these gates and there is one list of them.
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
pull_request:
|
pull_request:
|
||||||
|
workflow_call:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
@@ -43,7 +47,61 @@ jobs:
|
|||||||
echo "gofmt needed on:"; echo "$unformatted"; exit 1
|
echo "gofmt needed on:"; echo "$unformatted"; exit 1
|
||||||
fi
|
fi
|
||||||
- run: go vet ./...
|
- run: go vet ./...
|
||||||
- run: go test ./...
|
# -race: felis-api and the operator are mostly goroutines (watchers, the
|
||||||
|
# registry pruner, the backup scheduler, the rate limiters).
|
||||||
|
- run: go test -race ./...
|
||||||
|
# The version is pinned here and bumped by hand; Dependabot does not read `go run`.
|
||||||
|
- name: staticcheck
|
||||||
|
run: go run honnef.co/go/tools/cmd/[email protected] ./...
|
||||||
|
|
||||||
|
# Separate from the go job so a newly published advisory reads as what it is. govulncheck
|
||||||
|
# exits non-zero only for vulnerable code this module can actually reach, standard
|
||||||
|
# library included: setup-go installs the newest patch of go.mod's Go line, so a finding
|
||||||
|
# there means the Dockerfile's golang digest (which ships the release) needs a bump too.
|
||||||
|
vuln:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
||||||
|
|
||||||
|
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
|
||||||
|
with:
|
||||||
|
go-version-file: go.mod
|
||||||
|
|
||||||
|
- run: go run golang.org/x/vuln/cmd/[email protected] ./...
|
||||||
|
|
||||||
|
# The business stores' SQL against a real PostgreSQL (internal/pgint): the unit suites run
|
||||||
|
# on fakes, and PGRepo drifted from them three times while those stayed green. 13 is the
|
||||||
|
# oldest server a supported distribution installs (EL9), 18 the newest (Arch).
|
||||||
|
pgint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
postgres: ['13', '18']
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:${{ matrix.postgres }}
|
||||||
|
env:
|
||||||
|
POSTGRES_USER: felis
|
||||||
|
POSTGRES_PASSWORD: pgint
|
||||||
|
POSTGRES_DB: felis_pgint
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
||||||
|
options: >-
|
||||||
|
--health-cmd "pg_isready -U felis -d felis_pgint"
|
||||||
|
--health-interval 2s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 30
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
||||||
|
|
||||||
|
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
|
||||||
|
with:
|
||||||
|
go-version-file: go.mod
|
||||||
|
|
||||||
|
- run: go test -race -tags pgint -count=1 ./internal/pgint/
|
||||||
|
env:
|
||||||
|
FELIS_TEST_PG_URL: postgres://felis:pgint@localhost:5432/felis_pgint?sslmode=disable
|
||||||
|
|
||||||
shell:
|
shell:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -66,6 +124,16 @@ jobs:
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# A pinned release rather than the runner image's copy, so a runner update cannot
|
||||||
|
# change what fails. Warnings and errors fail the job; style notes (info) do not.
|
||||||
|
- name: shellcheck
|
||||||
|
run: |
|
||||||
|
curl -fsSL -o shellcheck.tar.xz \
|
||||||
|
https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.linux.x86_64.tar.xz
|
||||||
|
echo "8c3be12b05d5c177a04c29e3c78ce89ac86f1595681cab149b65b97c4e227198 shellcheck.tar.xz" | sha256sum -c
|
||||||
|
tar -xJf shellcheck.tar.xz
|
||||||
|
./shellcheck-v0.11.0/shellcheck -S warning $(git ls-files '*.sh')
|
||||||
|
|
||||||
- run: sh deploy/bootstrap_test.sh
|
- run: sh deploy/bootstrap_test.sh
|
||||||
|
|
||||||
panel:
|
panel:
|
||||||
|
|||||||
@@ -22,9 +22,9 @@
|
|||||||
# hash is not listed there, BEFORE it runs it. A release without the file installs by source
|
# hash is not listed there, BEFORE it runs it. A release without the file installs by source
|
||||||
# build instead.
|
# build instead.
|
||||||
#
|
#
|
||||||
# Two jobs, so the write token never meets the test suite: `build` runs the tests, Gradle and
|
# The write token never meets the test suite: `gates` (ci.yml) and `build` run the tests,
|
||||||
# the Docker build (each of which executes third-party code) with a read-only token and hands
|
# Gradle and the Docker build (each of which executes third-party code) with a read-only
|
||||||
# the binaries over as a workflow artifact; `publish` holds contents:write and runs only
|
# token, and `build` hands the binaries over as a workflow artifact; `publish` holds contents:write and runs only
|
||||||
# pinned actions and gh. Every action is pinned to a commit SHA (the tag in the trailing
|
# pinned actions and gh. Every action is pinned to a commit SHA (the tag in the trailing
|
||||||
# comment is for humans); .github/dependabot.yml proposes the bumps.
|
# comment is for humans); .github/dependabot.yml proposes the bumps.
|
||||||
name: release
|
name: release
|
||||||
@@ -37,44 +37,20 @@ permissions:
|
|||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
# A tag that ships red is worse than a tag that fails to ship. These are ci.yml's gates,
|
||||||
|
# called rather than copied: Go (race, vet, staticcheck), govulncheck, the PostgreSQL
|
||||||
|
# contract suite, shellcheck and the bootstrap tests, the panel, and the Java layer the
|
||||||
|
# binary EMBEDS (bootstrap_asset.go ships the plugin sources, so a tag whose plugins do
|
||||||
|
# not compile turns every install of that release into a failed bootstrap).
|
||||||
|
gates:
|
||||||
|
uses: ./.github/workflows/ci.yml
|
||||||
|
|
||||||
build:
|
build:
|
||||||
|
needs: gates
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
||||||
|
|
||||||
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
|
|
||||||
# A tag that ships red is worse than a tag that fails to ship.
|
|
||||||
- run: go vet ./...
|
|
||||||
- run: go test ./...
|
|
||||||
|
|
||||||
# The same reason, for the Java layer the binary EMBEDS: the release asset is
|
|
||||||
# the tree's plugin sources (bootstrap_asset.go), and a tag whose plugins don't
|
|
||||||
# compile turns every install of that release into a failed bootstrap. JDK 21
|
|
||||||
# gates the install-time plugins + codec/invite tests; JDK 17 gates the loader
|
|
||||||
# mods (their vendored wrappers fetch their own Gradle).
|
|
||||||
- uses: actions/setup-java@cf277c60eb25467037889841efdb72551f06f6c3 # v4.9.1
|
|
||||||
with:
|
|
||||||
distribution: temurin
|
|
||||||
java-version: '21'
|
|
||||||
|
|
||||||
- uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3
|
|
||||||
with:
|
|
||||||
gradle-version: '8.14'
|
|
||||||
|
|
||||||
- run: bash plugins/test.sh
|
|
||||||
|
|
||||||
- uses: actions/setup-java@cf277c60eb25467037889841efdb72551f06f6c3 # v4.9.1
|
|
||||||
with:
|
|
||||||
distribution: temurin
|
|
||||||
java-version: '17'
|
|
||||||
|
|
||||||
- uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3
|
|
||||||
|
|
||||||
- run: bash plugins/test-mods.sh
|
|
||||||
|
|
||||||
# Both architectures, because bootstrap's default release channel DOWNLOADS these
|
# Both architectures, because bootstrap's default release channel DOWNLOADS these
|
||||||
# rather than compiling on the target host — an arm64 host with no asset silently
|
# rather than compiling on the target host — an arm64 host with no asset silently
|
||||||
# falls back to a slow source build. Neither stage is emulated: the Dockerfile pins
|
# falls back to a slow source build. Neither stage is emulated: the Dockerfile pins
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ func extractTarGz(r io.Reader, root string) error {
|
|||||||
if err := os.MkdirAll(target, 0o755); err != nil {
|
if err := os.MkdirAll(target, 0o755); err != nil {
|
||||||
return fmt.Errorf("create %q: %w", name, err)
|
return fmt.Errorf("create %q: %w", name, err)
|
||||||
}
|
}
|
||||||
case tar.TypeReg, tar.TypeRegA:
|
case tar.TypeReg:
|
||||||
if err := os.MkdirAll(filepath.Dir(target), 0o755); err != nil {
|
if err := os.MkdirAll(filepath.Dir(target), 0o755); err != nil {
|
||||||
return fmt.Errorf("create parent of %q: %w", name, err)
|
return fmt.Errorf("create parent of %q: %w", name, err)
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-7
@@ -54,7 +54,7 @@
|
|||||||
# digests are pinned; a rerun moves an installer-managed JRE to the
|
# digests are pinned; a rerun moves an installer-managed JRE to the
|
||||||
# pinned build). Another feature version is checked against the
|
# pinned build). Another feature version is checked against the
|
||||||
# digest Adoptium's API publishes for it.
|
# digest Adoptium's API publishes for it.
|
||||||
# FELIS_GO_VERSION Go toolchain used to build the nano binary (default: 1.26.4)
|
# FELIS_GO_VERSION Go toolchain used to build the nano binary (default: 1.26.8)
|
||||||
# FELIS_GO_SHA256 sha256 of that version's linux tarball for this host's architecture.
|
# FELIS_GO_SHA256 sha256 of that version's linux tarball for this host's architecture.
|
||||||
# REQUIRED for a non-default FELIS_GO_VERSION; the default's is pinned.
|
# REQUIRED for a non-default FELIS_GO_VERSION; the default's is pinned.
|
||||||
# FELIS_K3S_VERSION k3s release a fresh install gets (default: v1.36.4+k3s1). An
|
# FELIS_K3S_VERSION k3s release a fresh install gets (default: v1.36.4+k3s1). An
|
||||||
@@ -214,9 +214,9 @@ FELIS_LEGACY_FORWARDING_SERVERS="${FELIS_LEGACY_FORWARDING_SERVERS:-legacy18}"
|
|||||||
# The Go tarball is unpacked and run as root, so the default version is pinned by the sha256
|
# The Go tarball is unpacked and run as root, so the default version is pinned by the sha256
|
||||||
# go.dev/dl publishes for each architecture install_go_toolchain handles. Move all three
|
# go.dev/dl publishes for each architecture install_go_toolchain handles. Move all three
|
||||||
# together; any other FELIS_GO_VERSION has to bring its own FELIS_GO_SHA256.
|
# together; any other FELIS_GO_VERSION has to bring its own FELIS_GO_SHA256.
|
||||||
GO_PINNED_VERSION="1.26.4"
|
GO_PINNED_VERSION="1.26.8"
|
||||||
GO_PINNED_SHA256_AMD64="1153d3d50e0ac764b447adfe05c2bcf08e889d42a02e0fe0259bd47f6733ad7f"
|
GO_PINNED_SHA256_AMD64="d0f743b33e8d8945e6b1f432edd15785c70507121d6e2a723b21285eddf8b57b"
|
||||||
GO_PINNED_SHA256_ARM64="ef758ae7c6cf9267c9c0ef080b8965f453d89ab2d25d9eb22de4405925238768"
|
GO_PINNED_SHA256_ARM64="211ffced9dcb9633a55eac6364816ec0ddd951389a740e88fa8b3337971bdda0"
|
||||||
FELIS_GO_VERSION="${FELIS_GO_VERSION:-$GO_PINNED_VERSION}"
|
FELIS_GO_VERSION="${FELIS_GO_VERSION:-$GO_PINNED_VERSION}"
|
||||||
FELIS_GO_SHA256="${FELIS_GO_SHA256:-}"
|
FELIS_GO_SHA256="${FELIS_GO_SHA256:-}"
|
||||||
# cloudflared runs as root on the edge, so it gets the same treatment: a pinned release and
|
# cloudflared runs as root on the edge, so it gets the same treatment: a pinned release and
|
||||||
@@ -1053,8 +1053,8 @@ install_k3s() {
|
|||||||
# registry-mirror restart below: both restart the agent, and a bootstrap that
|
# registry-mirror restart below: both restart the agent, and a bootstrap that
|
||||||
# proceeds early fails later with a misleading "not found"/timeout instead.
|
# proceeds early fails later with a misleading "not found"/timeout instead.
|
||||||
wait_for_node_ready() {
|
wait_for_node_ready() {
|
||||||
local i
|
local _
|
||||||
for i in $(seq 1 60); do
|
for _ in $(seq 1 60); do
|
||||||
if kube get nodes 2>/dev/null | grep -q ' Ready '; then
|
if kube get nodes 2>/dev/null | grep -q ' Ready '; then
|
||||||
ok "k3s node Ready"
|
ok "k3s node Ready"
|
||||||
return 0
|
return 0
|
||||||
@@ -3731,7 +3731,8 @@ write_nano_config() {
|
|||||||
# own 0700: that directory holds secrets, and install_nano_service reports the lockout
|
# own 0700: that directory holds secrets, and install_nano_service reports the lockout
|
||||||
# rather than this widening it.
|
# rather than this widening it.
|
||||||
if [ ! -d "$STATE_DIR" ]; then
|
if [ ! -d "$STATE_DIR" ]; then
|
||||||
mkdir -p -m 0755 "$STATE_DIR"
|
mkdir -p "$STATE_DIR"
|
||||||
|
chmod 0755 "$STATE_DIR"
|
||||||
elif [ ! -e "$SECRETS_ENV" ] && [ ! -e "$BOOTSTRAP_DONE" ]; then
|
elif [ ! -e "$SECRETS_ENV" ] && [ ! -e "$BOOTSTRAP_DONE" ]; then
|
||||||
chmod 0755 "$STATE_DIR"
|
chmod 0755 "$STATE_DIR"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ ivblock="$(awk '/^install_velocity\(\) \{/,/^}/' "$BS")"
|
|||||||
run_velocity_choice() { # FELIS_GAME_STACK FELIS_VELOCITY_VERSION lock-version
|
run_velocity_choice() { # FELIS_GAME_STACK FELIS_VELOCITY_VERSION lock-version
|
||||||
FELIS_GAME_STACK="$1" FELIS_VELOCITY_VERSION="$2" VELOCITY_VERSION="$3" VELOCITY_LATEST_MINOR=3.5.1 \
|
FELIS_GAME_STACK="$1" FELIS_VELOCITY_VERSION="$2" VELOCITY_VERSION="$3" VELOCITY_LATEST_MINOR=3.5.1 \
|
||||||
VELOCITY_JAR_URL=https://fill-data.papermc.io/v1/objects/aaa/velocity-3.5.1-615.jar VELOCITY_JAR_SHA256=aaa \
|
VELOCITY_JAR_URL=https://fill-data.papermc.io/v1/objects/aaa/velocity-3.5.1-615.jar VELOCITY_JAR_SHA256=aaa \
|
||||||
FELIS_VELOCITY_FORK_JAR= bash -c '
|
FELIS_VELOCITY_FORK_JAR='' bash -c '
|
||||||
set -Eeuo pipefail
|
set -Eeuo pipefail
|
||||||
log() { :; }
|
log() { :; }
|
||||||
die() { printf "DIE: %s\n" "$*"; exit 1; }
|
die() { printf "DIE: %s\n" "$*"; exit 1; }
|
||||||
@@ -993,23 +993,30 @@ rm -f "$mfile"
|
|||||||
pblock="$(awk '/^push_image_to_registry\(\) \{/,/^}/' "$BS")"
|
pblock="$(awk '/^push_image_to_registry\(\) \{/,/^}/' "$BS")"
|
||||||
[ -n "$pblock" ] || { echo "FAIL: no push_image_to_registry found in $BS"; exit 1; }
|
[ -n "$pblock" ] || { echo "FAIL: no push_image_to_registry found in $BS"; exit 1; }
|
||||||
|
|
||||||
run_push() { # ref [docker-push-exit]
|
pushdir="$(mktemp -d)"
|
||||||
REF="$1" PUSH_EXIT="${2:-0}" \
|
run_push() { # ref [failed-pushes-before-success] [registry-read-only]
|
||||||
|
REF="$1" PUSH_FAILS="${2:-0}" READONLY="${3:-0}" COUNT="$pushdir/count" \
|
||||||
REGISTRY_URL=registry.felis.svc:5000 REGISTRY_PUSH_HOST=127.0.0.1:5000 REGISTRY_DOCKER_CONFIG=/cfg \
|
REGISTRY_URL=registry.felis.svc:5000 REGISTRY_PUSH_HOST=127.0.0.1:5000 REGISTRY_DOCKER_CONFIG=/cfg \
|
||||||
bash -c '
|
bash -c '
|
||||||
log() { printf "LOG: %s\n" "$*"; }
|
log() { printf "LOG: %s\n" "$*"; }
|
||||||
warn() { printf "WARN: %s\n" "$*"; }
|
warn() { printf "WARN: %s\n" "$*"; }
|
||||||
die() { printf "DIE: %s\n" "$*"; exit 1; }
|
die() { printf "DIE: %s\n" "$*"; exit 1; }
|
||||||
ok() { :; }
|
ok() { :; }
|
||||||
|
sleep() { :; }
|
||||||
systemctl() { :; }
|
systemctl() { :; }
|
||||||
|
registry_read_only() { [ "$READONLY" = 1 ]; }
|
||||||
docker() {
|
docker() {
|
||||||
printf "DOCKER %s\n" "$*"
|
printf "DOCKER %s\n" "$*"
|
||||||
case " $* " in
|
case " $* " in
|
||||||
*" push "*) return "$PUSH_EXIT" ;;
|
*" push "*)
|
||||||
|
n="$(cat "$COUNT" 2>/dev/null || echo 0)"
|
||||||
|
echo $((n + 1)) > "$COUNT"
|
||||||
|
[ "$n" -ge "$PUSH_FAILS" ] ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
'"$pblock"'
|
'"$pblock"'
|
||||||
push_image_to_registry "$REF"'
|
push_image_to_registry "$REF"'
|
||||||
|
rm -f "$pushdir/count"
|
||||||
}
|
}
|
||||||
|
|
||||||
out="$(run_push registry.felis.svc:5000/felis/felis:demo)"
|
out="$(run_push registry.felis.svc:5000/felis/felis:demo)"
|
||||||
@@ -1025,6 +1032,16 @@ esac
|
|||||||
|
|
||||||
out="$(run_push registry.felis.svc:5000/felis/felis:demo 1)"
|
out="$(run_push registry.felis.svc:5000/felis/felis:demo 1)"
|
||||||
expect "a failed push fails the install loudly" "DIE: could not mirror" "$out"
|
expect "a failed push fails the install loudly" "DIE: could not mirror" "$out"
|
||||||
|
out="$(run_push registry.felis.svc:5000/felis/felis:demo 2 1)"
|
||||||
|
expect "a push refused during a GC window is retried" \
|
||||||
|
"WARN: the registry is read-only for garbage collection; retrying the push of 127.0.0.1:5000/felis/felis:demo in 30s (2/40)" "$out"
|
||||||
|
case "$out" in
|
||||||
|
*DIE:*) echo "FAIL a push that succeeds after the GC window must not fail the install"; fails=$((fails + 1)) ;;
|
||||||
|
*) echo "PASS a push that succeeds after the GC window completes" ;;
|
||||||
|
esac
|
||||||
|
expect "a GC window that never ends still fails the install" "DIE: could not mirror" \
|
||||||
|
"$(run_push registry.felis.svc:5000/felis/felis:demo 99 1)"
|
||||||
|
rm -rf "$pushdir"
|
||||||
|
|
||||||
# docker must be started ONCE for the whole batch: a start/stop pair per image trips
|
# docker must be started ONCE for the whole batch: a start/stop pair per image trips
|
||||||
# systemd's start rate limit ("start-limit-hit" — observed live; the 4th image was never
|
# systemd's start rate limit ("start-limit-hit" — observed live; the 4th image was never
|
||||||
@@ -1130,8 +1147,11 @@ expect "the running felis image is pinned" "CTR ctr images label registry.felis.
|
|||||||
expect "the registry image is pinned by digest" "CTR ctr images label docker.io/library/registry@${regdigest} io.cri-containerd.pinned=pinned" "$out"
|
expect "the registry image is pinned by digest" "CTR ctr images label docker.io/library/registry@${regdigest} io.cri-containerd.pinned=pinned" "$out"
|
||||||
expect "a previous felis tag is unpinned" "CTR ctr images label registry.felis.svc:5000/felis/felis:v1 io.cri-containerd.pinned=" "$out"
|
expect "a previous felis tag is unpinned" "CTR ctr images label registry.felis.svc:5000/felis/felis:v1 io.cri-containerd.pinned=" "$out"
|
||||||
expect "the old registry:2 tag is unpinned" "CTR ctr images label docker.io/library/registry:2 io.cri-containerd.pinned=" "$out"
|
expect "the old registry:2 tag is unpinned" "CTR ctr images label docker.io/library/registry:2 io.cri-containerd.pinned=" "$out"
|
||||||
|
# $'\n' is bash; this file runs under dash in CI.
|
||||||
|
nl='
|
||||||
|
'
|
||||||
case "$out" in
|
case "$out" in
|
||||||
*"registry@${regdigest} io.cri-containerd.pinned="$'\n'*) echo "FAIL: the current registry image must not be unpinned"; fails=$((fails + 1)) ;;
|
*"registry@${regdigest} io.cri-containerd.pinned=${nl}"*) echo "FAIL: the current registry image must not be unpinned"; fails=$((fails + 1)) ;;
|
||||||
esac
|
esac
|
||||||
case "$out" in
|
case "$out" in
|
||||||
*"limbo:demo io.cri"*) echo "FAIL: only the registry pod's images may be pinned or unpinned"; fails=$((fails + 1)) ;;
|
*"limbo:demo io.cri"*) echo "FAIL: only the registry pod's images may be pinned or unpinned"; fails=$((fails + 1)) ;;
|
||||||
@@ -1698,7 +1718,7 @@ printf 'JAVA_VERSION="25"\n' > "$vdir/jre/release"
|
|||||||
run_velocity_service() { # is-active(0|1)
|
run_velocity_service() { # is-active(0|1)
|
||||||
ACTIVE="$1" VELOCITY_SERVICE="$vdir/unit" VELOCITY_DIR="$vdir/v" JRE_DIR="$vdir/jre" \
|
ACTIVE="$1" VELOCITY_SERVICE="$vdir/unit" VELOCITY_DIR="$vdir/v" JRE_DIR="$vdir/jre" \
|
||||||
VELOCITY_FINGERPRINT="$vdir/fp" VELOCITY_USER=felis-velocity FELIS_GAME_PORT=25565 \
|
VELOCITY_FINGERPRINT="$vdir/fp" VELOCITY_USER=felis-velocity FELIS_GAME_PORT=25565 \
|
||||||
FELIS_LEGACY_FORWARDING_SERVERS= bash -c '
|
FELIS_LEGACY_FORWARDING_SERVERS='' bash -c '
|
||||||
set -Eeuo pipefail
|
set -Eeuo pipefail
|
||||||
ok() { printf "OK: %s\n" "$*"; }
|
ok() { printf "OK: %s\n" "$*"; }
|
||||||
felis_internal_ip() { printf "10.43.0.9"; }
|
felis_internal_ip() { printf "10.43.0.9"; }
|
||||||
@@ -1882,6 +1902,8 @@ expect "a v6 node address gets a v6 rule" "tcp dport 5432 ip6 saddr 2001:db8::7
|
|||||||
rm -rf "$fwdir"
|
rm -rf "$fwdir"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------------------
|
||||||
if [ "$fails" -eq 0 ]; then
|
if [ "$fails" -eq 0 ]; then
|
||||||
echo "ALL PASS"
|
echo "ALL PASS"
|
||||||
|
|||||||
@@ -44,8 +44,11 @@ resolve_latest_game_jars
|
|||||||
log "resolving the newest Velocity ${VELOCITY_LATEST_MINOR} build"
|
log "resolving the newest Velocity ${VELOCITY_LATEST_MINOR} build"
|
||||||
velocity="$(papermc_latest_jar velocity "$VELOCITY_LATEST_MINOR")" \
|
velocity="$(papermc_latest_jar velocity "$VELOCITY_LATEST_MINOR")" \
|
||||||
|| die "no Velocity build for ${VELOCITY_LATEST_MINOR}"
|
|| die "no Velocity build for ${VELOCITY_LATEST_MINOR}"
|
||||||
|
# shellcheck disable=SC2034 # read back through ${!key} below
|
||||||
VELOCITY_VERSION="$VELOCITY_LATEST_MINOR"
|
VELOCITY_VERSION="$VELOCITY_LATEST_MINOR"
|
||||||
|
# shellcheck disable=SC2034
|
||||||
VELOCITY_JAR_URL="${velocity% *}"
|
VELOCITY_JAR_URL="${velocity% *}"
|
||||||
|
# shellcheck disable=SC2034
|
||||||
VELOCITY_JAR_SHA256="${velocity##* }"
|
VELOCITY_JAR_SHA256="${velocity##* }"
|
||||||
|
|
||||||
tmp="$(mktemp)"
|
tmp="$(mktemp)"
|
||||||
|
|||||||
@@ -505,7 +505,7 @@ func (o OffsiteConfig) validate() error {
|
|||||||
return fmt.Errorf("config: [offsite] bucket %q must be a bare bucket name; put a key prefix in prefix", o.Bucket)
|
return fmt.Errorf("config: [offsite] bucket %q must be a bare bucket name; put a key prefix in prefix", o.Bucket)
|
||||||
}
|
}
|
||||||
if strings.Contains(o.Prefix, "..") {
|
if strings.Contains(o.Prefix, "..") {
|
||||||
return fmt.Errorf("config: [offsite] prefix %q must not contain ..", o.Prefix)
|
return fmt.Errorf("config: [offsite] prefix %q must not contain \"..\"", o.Prefix)
|
||||||
}
|
}
|
||||||
if o.DBKeep < 1 {
|
if o.DBKeep < 1 {
|
||||||
return fmt.Errorf("config: [offsite] db_keep %d must be at least 1", o.DBKeep)
|
return fmt.Errorf("config: [offsite] db_keep %d must be at least 1", o.DBKeep)
|
||||||
|
|||||||
@@ -81,13 +81,15 @@ type Gate struct {
|
|||||||
// New builds a Gate for upstream.
|
// New builds a Gate for upstream.
|
||||||
func New(upstream *url.URL, tokens map[string]string, log *slog.Logger) *Gate {
|
func New(upstream *url.URL, tokens map[string]string, log *slog.Logger) *Gate {
|
||||||
g := &Gate{Tokens: tokens, Upstream: upstream, Log: log}
|
g := &Gate{Tokens: tokens, Upstream: upstream, Log: log}
|
||||||
rp := httputil.NewSingleHostReverseProxy(upstream)
|
rp := &httputil.ReverseProxy{Rewrite: func(pr *httputil.ProxyRequest) {
|
||||||
base := rp.Director
|
pr.SetURL(upstream)
|
||||||
rp.Director = func(r *http.Request) {
|
// The registry builds upload Location URLs from Host: keep the one the client
|
||||||
base(r)
|
// dialled, not the loopback upstream.
|
||||||
|
pr.Out.Host = pr.In.Host
|
||||||
|
pr.SetXForwarded()
|
||||||
// The registry has no auth of its own; the credential stops here.
|
// The registry has no auth of its own; the credential stops here.
|
||||||
r.Header.Del("Authorization")
|
pr.Out.Header.Del("Authorization")
|
||||||
}
|
}}
|
||||||
// Blob uploads and pulls are streamed; flush as bytes arrive so a large layer
|
// Blob uploads and pulls are streamed; flush as bytes arrive so a large layer
|
||||||
// pull is not buffered in the gate.
|
// pull is not buffered in the gate.
|
||||||
rp.FlushInterval = -1
|
rp.FlushInterval = -1
|
||||||
|
|||||||
Reference in new issue
Block a user