Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 07f1ad0a6e | |||
| 3695fecbb6 | |||
| 72f1266078 | |||
| dd0014db83 | |||
| e2d850c2e9 |
@@ -16,8 +16,10 @@ if [[ "$DRY_RUN" == 1 ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
command -v docker >/dev/null || { echo 'docker is required to build the imgproxy runtime image' >&2; exit 1; }
|
command -v docker >/dev/null || { echo 'docker is required to build the imgproxy runtime image' >&2; exit 1; }
|
||||||
|
if ! docker image inspect "$IMAGE_REF" >/dev/null 2>&1; then
|
||||||
docker pull --platform linux/arm64 "$IMAGE_REF"
|
docker pull --platform linux/arm64 "$IMAGE_REF"
|
||||||
|
fi
|
||||||
docker tag "$IMAGE_REF" "$IMAGE_TAG"
|
docker tag "$IMAGE_REF" "$IMAGE_TAG"
|
||||||
docker save "$IMAGE_TAG" | gzip -c > "$OUT_DIR/imgproxy-runtime-image.tar.gz"
|
docker save "$IMAGE_TAG" | gzip -c > "$OUT_DIR/imgproxy-runtime-image.tar.gz"
|
||||||
shasum -a 256 "$OUT_DIR/imgproxy-runtime-image.tar.gz" > "$OUT_DIR/imgproxy-runtime-image.tar.gz.sha256"
|
(cd "$OUT_DIR" && shasum -a 256 imgproxy-runtime-image.tar.gz > imgproxy-runtime-image.tar.gz.sha256)
|
||||||
printf '%s\n' "$IMAGE_TAG" > "$OUT_DIR/image-tag.txt"
|
printf '%s\n' "$IMAGE_TAG" > "$OUT_DIR/image-tag.txt"
|
||||||
|
|||||||
@@ -11,18 +11,30 @@ test('imgproxy runtime pins an arm64 image digest', () => {
|
|||||||
assert.match(dockerfile, /FROM darthsim\/imgproxy@sha256:[a-f0-9]{64}/);
|
assert.match(dockerfile, /FROM darthsim\/imgproxy@sha256:[a-f0-9]{64}/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('builder reuses an already verified digest without a network pull', () => {
|
||||||
|
const builder = read('scripts/build-imgproxy-runtime-image.sh');
|
||||||
|
assert.match(builder, /docker image inspect "\$IMAGE_REF"/);
|
||||||
|
assert.match(builder, /shasum -a 256 imgproxy-runtime-image\.tar\.gz/);
|
||||||
|
});
|
||||||
|
|
||||||
test('installer uses a read-only storage mount and both required ports', () => {
|
test('installer uses a read-only storage mount and both required ports', () => {
|
||||||
const installer = read('scripts/install-imgproxy-runtime-prod.sh');
|
const installer = read('scripts/install-imgproxy-runtime-prod.sh');
|
||||||
assert.match(installer, /-p 127\.0\.0\.1:20082:8080/);
|
assert.match(installer, /-p 127\.0\.0\.1:20082:8080/);
|
||||||
assert.match(installer, /\$MINDSPACE_STORAGE_ROOT:\/mnt\/images:ro/);
|
assert.match(installer, /\$MINDSPACE_STORAGE_ROOT:\/mnt\/images:ro/);
|
||||||
assert.match(installer, /10\.10\.0\.2/);
|
assert.match(installer, /10\.10\.0\.2/);
|
||||||
assert.match(installer, /IMGPROXY_UPSTREAM/);
|
assert.match(installer, /IMGPROXY_UPSTREAM/);
|
||||||
|
assert.match(installer, /DOCKER_BIN/);
|
||||||
|
assert.match(installer, /seq 1 20/);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('release verifies checksums before loading the image and backs up launch state', () => {
|
test('release verifies checksums before loading the image and backs up launch state', () => {
|
||||||
const release = read('scripts/release-imgproxy-runtime-prod.sh');
|
const release = read('scripts/release-imgproxy-runtime-prod.sh');
|
||||||
assert.match(release, /shasum -a 256 -c/);
|
assert.match(release, /shasum -a 256 -c/);
|
||||||
assert.match(release, /docker load/);
|
assert.match(release, /shasum -a 256 "imgproxy-runtime-\$RELEASE_ID\.tar\.gz"/);
|
||||||
|
assert.match(release, /"\$DOCKER_BIN" load/);
|
||||||
|
assert.match(release, /DOCKER_BIN/);
|
||||||
assert.match(release, /imgproxy-compat-\$RELEASE_ID\.plist/);
|
assert.match(release, /imgproxy-compat-\$RELEASE_ID\.plist/);
|
||||||
assert.match(release, /img\.tkmind\.cn\/health/);
|
assert.match(release, /img\.tkmind\.cn\/health/);
|
||||||
|
assert.match(release, /release\/\*/);
|
||||||
|
assert.match(release, /rev-parse origin\/main/);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ RUNTIME_DIR="${IMGPROXY_RUNTIME_DIR:?IMGPROXY_RUNTIME_DIR is required}"
|
|||||||
IMAGE_TAG="${IMGPROXY_IMAGE_TAG:?IMGPROXY_IMAGE_TAG is required}"
|
IMAGE_TAG="${IMGPROXY_IMAGE_TAG:?IMGPROXY_IMAGE_TAG is required}"
|
||||||
CONTAINER="${IMGPROXY_CONTAINER:-memind-imgproxy}"
|
CONTAINER="${IMGPROXY_CONTAINER:-memind-imgproxy}"
|
||||||
NODE_BIN="${NODE_BIN:-/opt/homebrew/opt/node@24/bin/node}"
|
NODE_BIN="${NODE_BIN:-/opt/homebrew/opt/node@24/bin/node}"
|
||||||
|
DOCKER_BIN="${DOCKER_BIN:-/opt/homebrew/bin/docker}"
|
||||||
PLIST="$HOME/Library/LaunchAgents/cn.tkmind.imgproxy-compat.plist"
|
PLIST="$HOME/Library/LaunchAgents/cn.tkmind.imgproxy-compat.plist"
|
||||||
GUI="gui/$(id -u)"
|
GUI="gui/$(id -u)"
|
||||||
|
|
||||||
@@ -17,8 +18,8 @@ set +a
|
|||||||
: "${IMGPROXY_SIGNING_SALT:?missing IMGPROXY_SIGNING_SALT}"
|
: "${IMGPROXY_SIGNING_SALT:?missing IMGPROXY_SIGNING_SALT}"
|
||||||
: "${MINDSPACE_STORAGE_ROOT:?missing MINDSPACE_STORAGE_ROOT}"
|
: "${MINDSPACE_STORAGE_ROOT:?missing MINDSPACE_STORAGE_ROOT}"
|
||||||
|
|
||||||
docker rm -f "$CONTAINER" >/dev/null 2>&1 || true
|
"$DOCKER_BIN" rm -f "$CONTAINER" >/dev/null 2>&1 || true
|
||||||
docker run -d --name "$CONTAINER" --restart unless-stopped \
|
"$DOCKER_BIN" run -d --name "$CONTAINER" --restart unless-stopped \
|
||||||
-p 127.0.0.1:20082:8080 \
|
-p 127.0.0.1:20082:8080 \
|
||||||
-v "$MINDSPACE_STORAGE_ROOT:/mnt/images:ro" \
|
-v "$MINDSPACE_STORAGE_ROOT:/mnt/images:ro" \
|
||||||
-e IMGPROXY_LOCAL_FILESYSTEM_ROOT=/mnt/images \
|
-e IMGPROXY_LOCAL_FILESYSTEM_ROOT=/mnt/images \
|
||||||
@@ -53,4 +54,8 @@ launchctl bootout "$GUI/cn.tkmind.imgproxy-compat" 2>/dev/null || true
|
|||||||
launchctl bootstrap "$GUI" "$PLIST"
|
launchctl bootstrap "$GUI" "$PLIST"
|
||||||
launchctl enable "$GUI/cn.tkmind.imgproxy-compat"
|
launchctl enable "$GUI/cn.tkmind.imgproxy-compat"
|
||||||
launchctl kickstart -k "$GUI/cn.tkmind.imgproxy-compat"
|
launchctl kickstart -k "$GUI/cn.tkmind.imgproxy-compat"
|
||||||
|
for _ in $(seq 1 20); do
|
||||||
|
curl -fsS --max-time 2 http://10.10.0.2:20081/health >/dev/null && break
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
curl -fsS --max-time 3 http://10.10.0.2:20081/health >/dev/null
|
curl -fsS --max-time 3 http://10.10.0.2:20081/health >/dev/null
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ set -euo pipefail
|
|||||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
HOST="${STUDIO_HOST:-john@58.38.22.103}"
|
HOST="${STUDIO_HOST:-john@58.38.22.103}"
|
||||||
REMOTE_ROOT="${STUDIO_REMOTE_ROOT:-/Users/john/Project}"
|
REMOTE_ROOT="${STUDIO_REMOTE_ROOT:-/Users/john/Project}"
|
||||||
|
DOCKER_BIN="${DOCKER_BIN:-/opt/homebrew/bin/docker}"
|
||||||
RUNTIME_BASE="$REMOTE_ROOT/imgproxy-runtime"
|
RUNTIME_BASE="$REMOTE_ROOT/imgproxy-runtime"
|
||||||
INCOMING="$REMOTE_ROOT/incoming/imgproxy-runtime"
|
INCOMING="$REMOTE_ROOT/incoming/imgproxy-runtime"
|
||||||
RELEASE_ID="$(date +%Y%m%d-%H%M%S)-$(git -C "$ROOT" rev-parse --short HEAD)"
|
RELEASE_ID="$(date +%Y%m%d-%H%M%S)-$(git -C "$ROOT" rev-parse --short HEAD)"
|
||||||
@@ -13,9 +14,10 @@ TMP="$(mktemp -d "${TMPDIR:-/tmp}/imgproxy-runtime-release.XXXXXX")"
|
|||||||
cleanup() { rm -rf "$TMP"; }
|
cleanup() { rm -rf "$TMP"; }
|
||||||
trap cleanup EXIT
|
trap cleanup EXIT
|
||||||
|
|
||||||
[[ "$(git -C "$ROOT" branch --show-current)" == "main" ]] || { echo 'imgproxy production release must run from main' >&2; exit 1; }
|
|
||||||
[[ -z "$(git -C "$ROOT" status --porcelain)" ]] || { echo 'worktree must be clean' >&2; exit 1; }
|
|
||||||
git -C "$ROOT" fetch origin main --quiet
|
git -C "$ROOT" fetch origin main --quiet
|
||||||
|
branch="$(git -C "$ROOT" branch --show-current)"
|
||||||
|
[[ "$branch" == release/* ]] || { echo 'imgproxy production release must run from a release/* branch' >&2; exit 1; }
|
||||||
|
[[ -z "$(git -C "$ROOT" status --porcelain)" ]] || { echo 'worktree must be clean' >&2; exit 1; }
|
||||||
[[ "$(git -C "$ROOT" rev-parse HEAD)" == "$(git -C "$ROOT" rev-parse origin/main)" ]] || { echo 'main must match origin/main' >&2; exit 1; }
|
[[ "$(git -C "$ROOT" rev-parse HEAD)" == "$(git -C "$ROOT" rev-parse origin/main)" ]] || { echo 'main must match origin/main' >&2; exit 1; }
|
||||||
bash "$ROOT/scripts/check-release-ready.sh"
|
bash "$ROOT/scripts/check-release-ready.sh"
|
||||||
|
|
||||||
@@ -30,7 +32,7 @@ cp "$IMAGE_DIR"/* "$TMP/runtime/"
|
|||||||
cp "$ROOT/scripts/install-imgproxy-runtime-prod.sh" "$ROOT/scripts/imgproxy-compat-proxy.mjs" "$TMP/runtime/"
|
cp "$ROOT/scripts/install-imgproxy-runtime-prod.sh" "$ROOT/scripts/imgproxy-compat-proxy.mjs" "$TMP/runtime/"
|
||||||
chmod 755 "$TMP/runtime/install-imgproxy-runtime-prod.sh"
|
chmod 755 "$TMP/runtime/install-imgproxy-runtime-prod.sh"
|
||||||
tar -C "$TMP" -czf "$TMP/imgproxy-runtime-$RELEASE_ID.tar.gz" runtime
|
tar -C "$TMP" -czf "$TMP/imgproxy-runtime-$RELEASE_ID.tar.gz" runtime
|
||||||
shasum -a 256 "$TMP/imgproxy-runtime-$RELEASE_ID.tar.gz" > "$TMP/imgproxy-runtime-$RELEASE_ID.tar.gz.sha256"
|
(cd "$TMP" && shasum -a 256 "imgproxy-runtime-$RELEASE_ID.tar.gz" > "imgproxy-runtime-$RELEASE_ID.tar.gz.sha256")
|
||||||
|
|
||||||
ssh -o BatchMode=yes "$HOST" "mkdir -p '$INCOMING'"
|
ssh -o BatchMode=yes "$HOST" "mkdir -p '$INCOMING'"
|
||||||
scp -q "$TMP/imgproxy-runtime-$RELEASE_ID.tar.gz" "$TMP/imgproxy-runtime-$RELEASE_ID.tar.gz.sha256" "$HOST:$INCOMING/"
|
scp -q "$TMP/imgproxy-runtime-$RELEASE_ID.tar.gz" "$TMP/imgproxy-runtime-$RELEASE_ID.tar.gz.sha256" "$HOST:$INCOMING/"
|
||||||
@@ -46,7 +48,7 @@ cp "$HOME/Library/LaunchAgents/cn.tkmind.imgproxy-compat.plist" "$RUNTIME_BASE/b
|
|||||||
tar -xzf "$archive" -C "$release_dir" --strip-components=1
|
tar -xzf "$archive" -C "$release_dir" --strip-components=1
|
||||||
cd "$release_dir"
|
cd "$release_dir"
|
||||||
shasum -a 256 -c imgproxy-runtime-image.tar.gz.sha256
|
shasum -a 256 -c imgproxy-runtime-image.tar.gz.sha256
|
||||||
gunzip -c imgproxy-runtime-image.tar.gz | docker load
|
gunzip -c imgproxy-runtime-image.tar.gz | "$DOCKER_BIN" load
|
||||||
image_tag="$(cat image-tag.txt)"
|
image_tag="$(cat image-tag.txt)"
|
||||||
IMGPROXY_RUNTIME_DIR="$release_dir" IMGPROXY_IMAGE_TAG="$image_tag" bash ./install-imgproxy-runtime-prod.sh
|
IMGPROXY_RUNTIME_DIR="$release_dir" IMGPROXY_IMAGE_TAG="$image_tag" bash ./install-imgproxy-runtime-prod.sh
|
||||||
ln -sfn "$release_dir" "$RUNTIME_BASE/current"
|
ln -sfn "$release_dir" "$RUNTIME_BASE/current"
|
||||||
|
|||||||
Reference in New Issue
Block a user