Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,9 @@ check:

serve:
uv run --frozen python3 -m server.main

bundle:
./scripts/bundler.sh

install:
./scripts/install.sh
29 changes: 29 additions & 0 deletions scripts/bundler.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env bash
set -euo pipefail

BINARY_NAME="tiles"
DIST_DIR="dist"
SERVER_DIR="server"
TARGET="release"

VERSION=$(grep '^version' Cargo.toml | head -1 | awk -F'"' '{print $2}')
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Validate VERSION extraction and handle edge cases.

The version extraction assumes a specific format in Cargo.toml and does not validate the result. If the pattern fails to match or the field is malformed, VERSION will be empty, leading to a malformed tarball name.

Apply this diff to add validation:

 VERSION=$(grep '^version' Cargo.toml | head -1 | awk -F'"' '{print $2}')
+if [[ -z "$VERSION" ]]; then
+  echo "❌ Error: Could not extract version from Cargo.toml" >&2
+  exit 1
+fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
VERSION=$(grep '^version' Cargo.toml | head -1 | awk -F'"' '{print $2}')
VERSION=$(grep '^version' Cargo.toml | head -1 | awk -F'"' '{print $2}')
if [[ -z "$VERSION" ]]; then
echo "❌ Error: Could not extract version from Cargo.toml" >&2
exit 1
fi
🤖 Prompt for AI Agents
In scripts/bundler.sh around line 9, the VERSION extraction from Cargo.toml can
yield an empty or malformed value if the expected pattern isn't present; update
the script to validate the extracted VERSION is non-empty and matches a
semver-like pattern (e.g., digits and dots), and if validation fails print a
clear error to stderr and exit non‑zero to avoid creating a malformed tarball
name; optionally attempt a safer extraction (use a more robust grep/regex)
before validating.

OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)
OUT_NAME="${BINARY_NAME}-v${VERSION}-${ARCH}-${OS}"

echo "🚀 Building ${BINARY_NAME} (${TARGET} mode)..."
cargo build --${TARGET}

mkdir -p "${DIST_DIR}/tmp"
cp "target/${TARGET}/${BINARY_NAME}" "${DIST_DIR}/tmp/"
cp -r "${SERVER_DIR}" "${DIST_DIR}/tmp/"

rm -rf "${DIST_DIR}/tmp/server/__pycache__"
rm -rf "${DIST_DIR}/tmp/server/.venv"

echo "📦 Creating ${OUT_NAME}.tar.gz..."
tar -czf "${DIST_DIR}/${OUT_NAME}.tar.gz" -C "${DIST_DIR}/tmp" .

rm -rf "${DIST_DIR}/tmp"

echo "✅ Bundle created: ${DIST_DIR}/${OUT_NAME}.tar.gz"
71 changes: 71 additions & 0 deletions scripts/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/usr/bin/env bash
set -euo pipefail

ENV="dev" # prod is another env, try taking it from github env
REPO="tilesprivacy/tilekit"
# VERSION="${TILES_VERSION:-latest}"
VERSION="0.1.0"
INSTALL_DIR="$HOME/.local/bin" # CLI install location
SERVER_DIR="$HOME/.local/share/tiles/server" # Python server folder
TMPDIR="$(mktemp -d)"
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)


log() { echo -e "\033[1;36m$*\033[0m"; }
err() { echo -e "\033[1;31m$*\033[0m" >&2; exit 1; }

echo "🔍 Checking Python..."
if ! command -v python3 >/dev/null 2>&1; then
log "⚠️ Python 3.10+ not found."
if [[ "$OS" == "darwin" ]]; then
log "Installing via Homebrew..."
brew install python || err "Could not install Python automatically. Please install manually."
elif [[ -f /etc/debian_version ]]; then
log "Installing via apt..."
sudo apt-get update -y && sudo apt-get install -y python3 python3-venv
else
err "Please install Python manually: https://www.python.org/downloads/"
fi
fi
Comment on lines +18 to +30
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Python version not validated despite "3.10+" requirement.

The log message mentions "Python 3.10+" but the script only checks if python3 exists, not its version. If an older Python 3 is installed, the installation may fail later during uv sync.

Apply this diff to add version validation:

 echo "🔍 Checking Python..."
 if ! command -v python3 >/dev/null 2>&1; then
   log "⚠️  Python 3.10+ not found."
+  # Install Python
   if [[ "$OS" == "darwin" ]]; then
     log "Installing via Homebrew..."
     brew install python || err "Could not install Python automatically. Please install manually."
   elif [[ -f /etc/debian_version ]]; then
     log "Installing via apt..."
     sudo apt-get update -y && sudo apt-get install -y python3 python3-venv
   else
     err "Please install Python manually: https://www.python.org/downloads/"
   fi
+fi
+
+# Validate Python version
+PYTHON_VERSION=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")' 2>/dev/null || echo "0.0")
+REQUIRED_VERSION="3.10"
+if ! python3 -c "import sys; exit(0 if sys.version_info >= (3, 10) else 1)" 2>/dev/null; then
+  err "Python ${REQUIRED_VERSION}+ is required, but found ${PYTHON_VERSION}. Please upgrade."
 fi


🏁 Script executed:

#!/bin/bash
# Examine the full install.sh file to understand context
cat scripts/install.sh

Length of output: 2245


🏁 Script executed:

#!/bin/bash
# Search for Python version requirements in the repository
rg -n "3\.10|python" --type=toml --type=txt --type=yaml -C2 | head -50

Length of output: 2587


🏁 Script executed:

#!/bin/bash
# Check if there's a uv.lock or pyproject.toml with Python version spec
fd -e toml -e lock | xargs ls -la 2>/dev/null | head -20

Length of output: 333


Python version not validated despite 3.10+ requirement.

The script checks only if python3 exists but never validates its version. The server/pyproject.toml requires >=3.10, so a user with Python 3.9 would pass the check yet fail later during uv sync.

Apply the suggested diff to add version validation after the installation block:

+# Validate Python version
+PYTHON_VERSION=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")' 2>/dev/null || echo "0.0")
+REQUIRED_VERSION="3.10"
+if ! python3 -c "import sys; exit(0 if sys.version_info >= (3, 10) else 1)" 2>/dev/null; then
+  err "Python ${REQUIRED_VERSION}+ is required, but found ${PYTHON_VERSION}. Please upgrade."
+fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
echo "🔍 Checking Python..."
if ! command -v python3 >/dev/null 2>&1; then
log "⚠️ Python 3.10+ not found."
if [[ "$OS" == "darwin" ]]; then
log "Installing via Homebrew..."
brew install python || err "Could not install Python automatically. Please install manually."
elif [[ -f /etc/debian_version ]]; then
log "Installing via apt..."
sudo apt-get update -y && sudo apt-get install -y python3 python3-venv
else
err "Please install Python manually: https://www.python.org/downloads/"
fi
fi
echo "🔍 Checking Python..."
if ! command -v python3 >/dev/null 2>&1; then
log "⚠️ Python 3.10+ not found."
if [[ "$OS" == "darwin" ]]; then
log "Installing via Homebrew..."
brew install python || err "Could not install Python automatically. Please install manually."
elif [[ -f /etc/debian_version ]]; then
log "Installing via apt..."
sudo apt-get update -y && sudo apt-get install -y python3 python3-venv
else
err "Please install Python manually: https://www.python.org/downloads/"
fi
fi
# Validate Python version
PYTHON_VERSION=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")' 2>/dev/null || echo "0.0")
REQUIRED_VERSION="3.10"
if ! python3 -c "import sys; exit(0 if sys.version_info >= (3, 10) else 1)" 2>/dev/null; then
err "Python ${REQUIRED_VERSION}+ is required, but found ${PYTHON_VERSION}. Please upgrade."
fi
🤖 Prompt for AI Agents
In scripts/install.sh around lines 18 to 30, the script only checks for the
existence of python3 but does not verify the version requirement (>=3.10); after
the install/installation branch completes, run a Python version check using
python3 to ensure sys.version_info >= (3,10) and fail with a clear error and
non-zero exit if the installed python3 is older than 3.10 (or if the check
fails); log a helpful message directing the user to upgrade/install the correct
Python version and stop the script so downstream steps don't break.


echo "🔍 Checking uv..."
if ! command -v uv >/dev/null 2>&1; then
log "⬇️ Installing uv..."
curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
fi
Comment on lines +32 to +37
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Piping remote script to shell without verification poses security risk.

Downloading and executing https://astral.sh/uv/install.sh without checksum or signature verification can be exploited if the download is intercepted or the source is compromised.

Consider adding checksum verification or at least document this security consideration:

log "⬇️  Installing uv..."
# Note: This downloads and executes a script from the internet.
# For enhanced security, consider verifying checksums.
curl -LsSf https://astral.sh/uv/install.sh | sh

Alternatively, download the script first, verify its checksum, then execute it.

🤖 Prompt for AI Agents
In scripts/install.sh around lines 32 to 37, avoid piping the remote install
script directly to sh; instead download the script to a temporary file,
obtain/expect a checksum or signature (or fetch a published checksum from a
trusted URL), verify the downloaded file against that checksum/signature, and
only then execute the local file (or abort on mismatch). If no checksum is
available, log a clear warning and require explicit user confirmation before
executing the downloaded script; keep exporting PATH after successful install.
Ensure the script fails fast on verification errors and does not execute
unverified remote code.


log "⬇️ Downloading Tiles (${VERSION}) for ${ARCH}-${OS}..."



if [[ "$ENV" == "prod" ]]; then
TAR_URL="https://github.com/${REPO}/releases/download/${VERSION}/tiles-v${VERSION}-${ARCH}-${OS}.tar.gz"
curl -fsSL -o "${TMPDIR}/tiles.tar.gz" "$TAR_URL"
else
# Installer suppose to ran from tilekit root folder after running the bundler
mv "dist/tiles-v${VERSION}-${ARCH}-${OS}.tar.gz" "${TMPDIR}/tiles.tar.gz"
Comment on lines +47 to +48
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Use cp instead of mv to preserve source tarball.

Using mv removes the source tarball from the dist/ directory. If the installer is run multiple times during development or if the installation fails midway, the source tarball will be missing for subsequent attempts.

Apply this diff:

   # Installer suppose to ran from tilekit root folder after running the bundler
-  mv "dist/tiles-v${VERSION}-${ARCH}-${OS}.tar.gz" "${TMPDIR}/tiles.tar.gz" 
+  cp "dist/tiles-v${VERSION}-${ARCH}-${OS}.tar.gz" "${TMPDIR}/tiles.tar.gz" 
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Installer suppose to ran from tilekit root folder after running the bundler
mv "dist/tiles-v${VERSION}-${ARCH}-${OS}.tar.gz" "${TMPDIR}/tiles.tar.gz"
# Installer suppose to ran from tilekit root folder after running the bundler
cp "dist/tiles-v${VERSION}-${ARCH}-${OS}.tar.gz" "${TMPDIR}/tiles.tar.gz"
🤖 Prompt for AI Agents
In scripts/install.sh around lines 47-48, the installer currently uses mv which
removes the source tarball from dist/; change the command to copy the tarball
instead (use cp -a or cp --preserve=mode,timestamps) to copy
"dist/tiles-v${VERSION}-${ARCH}-${OS}.tar.gz" to "${TMPDIR}/tiles.tar.gz" so the
original remains for retrying or debugging, and ensure the cp command checks for
errors (exit non-zero) as mv did.

fi
Comment on lines +43 to +49
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Validate tarball exists before proceeding.

In dev mode, the script assumes the bundled tarball exists but doesn't verify it. If the bundler wasn't run or failed, the mv/cp will fail with an unclear error.

Apply this diff to add validation:

 if [[ "$ENV" == "prod" ]]; then
   TAR_URL="https://github.com/${REPO}/releases/download/${VERSION}/tiles-v${VERSION}-${ARCH}-${OS}.tar.gz"
   curl -fsSL -o "${TMPDIR}/tiles.tar.gz" "$TAR_URL"
 else
   # Installer suppose to ran from tilekit root folder after running the bundler
+  TARBALL="dist/tiles-v${VERSION}-${ARCH}-${OS}.tar.gz"
+  if [[ ! -f "$TARBALL" ]]; then
+    err "Tarball not found at $TARBALL. Run 'just bundle' first."
+  fi
-  mv "dist/tiles-v${VERSION}-${ARCH}-${OS}.tar.gz" "${TMPDIR}/tiles.tar.gz" 
+  cp "$TARBALL" "${TMPDIR}/tiles.tar.gz"
 fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if [[ "$ENV" == "prod" ]]; then
TAR_URL="https://github.com/${REPO}/releases/download/${VERSION}/tiles-v${VERSION}-${ARCH}-${OS}.tar.gz"
curl -fsSL -o "${TMPDIR}/tiles.tar.gz" "$TAR_URL"
else
# Installer suppose to ran from tilekit root folder after running the bundler
mv "dist/tiles-v${VERSION}-${ARCH}-${OS}.tar.gz" "${TMPDIR}/tiles.tar.gz"
fi
if [[ "$ENV" == "prod" ]]; then
TAR_URL="https://github.com/${REPO}/releases/download/${VERSION}/tiles-v${VERSION}-${ARCH}-${OS}.tar.gz"
curl -fsSL -o "${TMPDIR}/tiles.tar.gz" "$TAR_URL"
else
# Installer suppose to ran from tilekit root folder after running the bundler
TARBALL="dist/tiles-v${VERSION}-${ARCH}-${OS}.tar.gz"
if [[ ! -f "$TARBALL" ]]; then
err "Tarball not found at $TARBALL. Run 'just bundle' first."
fi
cp "$TARBALL" "${TMPDIR}/tiles.tar.gz"
fi
🤖 Prompt for AI Agents
In scripts/install.sh around lines 43 to 49, the dev branch assumes the bundled
tarball exists and blindly runs mv which will fail with an unclear error if the
bundler didn't produce the file; add an existence check for
"dist/tiles-v${VERSION}-${ARCH}-${OS}.tar.gz" before moving it, and if the file
is missing print a clear error message to stderr and exit with a non-zero status
(otherwise perform the mv to "${TMPDIR}/tiles.tar.gz").


echo "⬇️ Installing tiles..."
# Lets point to tile repo
tar -xzf "${TMPDIR}/tiles.tar.gz" -C "${TMPDIR}"

log "📦 Installing tiles binary to ${INSTALL_DIR}..."
mkdir -p "${INSTALL_DIR}"
install -m 755 "${TMPDIR}/tiles" "${INSTALL_DIR}/tiles"

log "📦 Installing Python server to ${SERVER_DIR}..."
mkdir -p "${SERVER_DIR}"
cp -r "${TMPDIR}/server"/* "${SERVER_DIR}/"

log "🔧 Setting up Python environment..."
cd "${SERVER_DIR}"
uv sync --frozen || err "Dependency setup failed."

rm -rf "${TMPDIR}"

log "✅ Tiles installed successfully!"
log ""
log "👉 Make sure ${INSTALL_DIR} is in your PATH."