[tool_alias]
railpack = "github:railwayapp/railpack"
buildkit = "github:moby/buildkit"

[tools]
minikube = "1.38.1"
pack = "0.39.0"
railpack = "0.15.1"
buildkit = "0.28.0"
"cargo:sqlx-cli" = "latest"
"cargo:cargo-all-features" = "latest"
mdbook = "latest"
helm = "latest"
rust = { version = "1.95.0", profile = "default" }
kubectl = "latest"
k9s = "latest"

[tasks."sqlx:prepare"]
description = "Prepare the SQLX query cache that needs to be committed for building with SQLX_OFFLINE=true."
run = "cargo sqlx prepare -- --features cli,backend --all-targets"

[tasks."sqlx:check"]
description = "Check that all SQLX queries are valid."
run = "cargo sqlx prepare --check -- --features cli,backend --all-targets"

[tasks.lint]
description = "Run all linting checks (clippy, formatting, sqlx, helm)."
run = """
cargo all-features check --all-targets
cargo all-features clippy --all-targets -- -D warnings
cargo fmt --all -- --check
mise sqlx:check
helm lint helm/rise
"""
env.SQLX_OFFLINE = true

[tasks."config:schema:generate"]
description = "Generate the backend settings JSON schema."
run = "cargo run --features cli,backend -- backend config-schema > docs/schemas/backend-settings.schema.json"
env.SQLX_OFFLINE = true

[tasks."config:schema:check"]
description = "Verify the committed backend settings JSON schema is up to date."
run = "mise config:schema:generate && git --no-pager diff --exit-code -- docs/schemas/backend-settings.schema.json"
env.SQLX_OFFLINE = true

[tasks."docs:serve"]
description = "Serve documentation with live reload in port 3001."
run = "mdbook serve -p 3001 --open"

[tasks."db:nuke"]
description = "Drop and recreate the development database. USE WITH CAUTION."
run = """
set -x
docker compose down -v postgres
docker compose up postgres -d
"""

[tasks."db:migrate"]
description = "Run database migrations. Run before building the backend."
run = "docker compose up postgres -d && sleep 2 && sqlx migrate run"

[tasks."backend:deps"]
description = "Start all backend dependencies with docker compose."
run = "docker compose up -d"

[tasks."backend:run"]
description = "Run the backend server."
depends = ["backend:deps", "db:migrate"]
run = "cargo run --features cli,backend -- backend server"
alias = "br"

[tasks."backend:run-container"]
description = "Build and run the backend server in its container (host network). Useful to validate the containerized version works as intended."
depends = ["backend:deps", "db:migrate"]
run = "docker build . -t rise --target rise && docker run --rm --network host -v $PWD/config:/etc/rise:ro -v $HOME/.kube:/root/.kube:ro -v $HOME/.minikube:$HOME/.minikube:ro -e DATABASE_URL=$DATABASE_URL -e RISE_CONFIG_DIR=/etc/rise -e RISE_CONFIG_RUN_MODE=development rise backend server"

[tasks."frontend:dev"]
description = "Run the Vite frontend development server."
run = "cd frontend && npm install && npm run dev"

[tasks."frontend:build"]
description = "Build the frontend bundle for embedding in the backend binary."
run = """
cd frontend
npm install
npm run build
cp dist/index.html ../static/
cp -r dist/assets/* ../static/assets/
"""

[tasks."dist:build"]
description = "Build local release artifacts using cargo-dist."
run = """
cargo install cargo-dist --locked
cargo dist build --target x86_64-unknown-linux-gnu --target x86_64-apple-darwin --target aarch64-apple-darwin
"""

[tasks."setup:hosts"]
description = "Ensure /etc/hosts has rise-registry and rise.local entries (idempotent)."
run = """
set -x
# Remove any existing entries and re-add to ensure correctness
sudo sed -i '/\\brise-registry\\b/d; /\\brise\\.local\\b/d' /etc/hosts
echo '127.0.0.1 rise-registry' | sudo tee -a /etc/hosts
echo '127.0.0.1 rise.local' | sudo tee -a /etc/hosts
"""

[tasks."setup:docker"]
description = "Ensure Docker daemon has insecure-registries configured for the local registry (idempotent)."
run = """
set -x
DAEMON_JSON="/etc/docker/daemon.json"
DAEMON_DIR=$(dirname "$DAEMON_JSON")
REQUIRED_REGISTRIES='["rise-registry:5000","localhost:5000","127.0.0.1:5000"]'
if [ ! -d "$DAEMON_DIR" ]; then
  echo "Skipping Docker daemon config because $DAEMON_DIR does not exist."
  exit 0
fi
if [ ! -f "$DAEMON_JSON" ]; then
  echo "Creating $DAEMON_JSON with insecure-registries..."
  echo "{\"insecure-registries\": $REQUIRED_REGISTRIES}" | sudo tee "$DAEMON_JSON"
  sudo systemctl restart docker || true
elif ! grep -q 'rise-registry:5000' "$DAEMON_JSON"; then
  echo "Adding insecure-registries to existing $DAEMON_JSON..."
  UPDATED=$(jq --argjson regs "$REQUIRED_REGISTRIES" '.["insecure-registries"] = ((.["insecure-registries"] // []) + $regs | unique)' "$DAEMON_JSON")
  echo "$UPDATED" | sudo tee "$DAEMON_JSON" > /dev/null
  echo "Restarting Docker..."
  sudo systemctl restart docker || true
else
  echo "Docker daemon already configured."
fi
"""

[tasks."minikube:up"]
description = "Start Minikube with local Docker registry access and ingress port-forwarding."
depends = ["setup:hosts", "setup:docker"]
run = """
set -x

docker compose up -d registry
NETWORK_NAME=rise_default
REGISTRY_NAME=rise-registry
REGISTRY_DIR="/etc/containerd/certs.d/localhost:5000"

minikube delete
minikube start --driver=docker --insecure-registry="${REGISTRY_NAME}:5000" --memory=4096mb --cpus=2 --cni=calico
minikube addons enable ingress

for node in $(minikube node list | awk '{print $1}'); do
  docker exec "${node}" mkdir -p "${REGISTRY_DIR}"
  cat <<EOF | docker exec -i "${node}" cp /dev/stdin "${REGISTRY_DIR}/hosts.toml"
[host."http://${REGISTRY_NAME}:5000"]
EOF
done

docker network connect "${NETWORK_NAME}" minikube || true

echo
echo "Minikube started. Port-forwarding ingress-nginx-controller to localhost:8080 (HTTP) and localhost:8443 (HTTPS)..."
echo

kubectl port-forward --namespace ingress-nginx svc/ingress-nginx-controller 8080:80 8443:443 &
echo "Port-forward running in background (PID: $!)"
"""

[tasks."minikube:down"]
description = "Stop and delete Minikube."
run = "minikube delete"

[tasks."k3s:up"]
depends = ["setup:hosts", "setup:docker"]
run = """
set -x

# Configure K3s registries for insecure access to rise-registry:5000
sudo mkdir -p /etc/rancher/k3s
sudo tee /etc/rancher/k3s/registries.yaml > /dev/null <<EOF
mirrors:
  "rise-registry:5000":
    endpoint:
      - "http://rise-registry:5000"
EOF

# Ensure the local Docker registry is running
docker compose up -d registry

# Install K3s
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--flannel-backend=none --cluster-cidr=192.168.0.0/16 --disable-network-policy --disable=traefik" sh -
sleep 10
mkdir -p ~/.kube
sudo cat /etc/rancher/k3s/k3s.yaml > ~/.kube/config
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.31.4/manifests/operator-crds.yaml --server-side --force-conflicts
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.31.4/manifests/tigera-operator.yaml --server-side --force-conflicts
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.31.4/manifests/custom-resources.yaml --server-side --force-conflicts
helm upgrade --install --repo https://kubernetes.github.io/ingress-nginx ingress-nginx --namespace ingress-nginx ingress-nginx --create-namespace

set +x
echo
echo
echo "Note: You need to apply the configuration from config/k3s.yaml for Rise-deployed apps to work properly."
echo "Double-check that the IP in the configuration matches that of the node in K3s:"
echo
echo "K3s internal IP: $(kubectl get node $(hostname) -o jsonpath='{.metadata.annotations.k3s\\.io/internal-ip}')"
echo
echo '```'
cat config/k3s.yaml
echo '```'
"""

[tasks."test:e2e-build"]
description = "Run end-to-end build backend tests (all or specific backends)."
run = "bash tests/e2e-build/run.sh"

[tasks."k3s:down"]
run = """
sudo /usr/local/bin/k3s-uninstall.sh
"""
