feat: create start:e2e and test:e2e scripts to launch tests easily
This commit is contained in:
parent
f389d51819
commit
6bbd950d15
6 changed files with 398 additions and 338 deletions
101
docker-compose.e2e.yml
Normal file
101
docker-compose.e2e.yml
Normal file
|
@ -0,0 +1,101 @@
|
|||
version: '3.7'
|
||||
|
||||
services:
|
||||
reverse-proxy:
|
||||
container_name: reverse-proxy
|
||||
image: traefik:v2.8
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 8080:8080
|
||||
- ${NGINX_PORT-80}:80
|
||||
command: --providers.docker
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- ${PWD}/traefik:/root/.config
|
||||
- ${PWD}/traefik/shared:/shared
|
||||
networks:
|
||||
- tipi_main_network
|
||||
|
||||
tipi-db:
|
||||
container_name: tipi-db
|
||||
image: postgres:14
|
||||
restart: unless-stopped
|
||||
stop_grace_period: 1m
|
||||
ports:
|
||||
- 5432:5432
|
||||
environment:
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
POSTGRES_USER: ${POSTGRES_USERNAME}
|
||||
POSTGRES_DB: ${POSTGRES_DBNAME}
|
||||
healthcheck:
|
||||
test: ['CMD-SHELL', 'pg_isready -d tipi -U tipi']
|
||||
interval: 5s
|
||||
timeout: 10s
|
||||
retries: 120
|
||||
networks:
|
||||
- tipi_main_network
|
||||
|
||||
tipi-redis:
|
||||
container_name: tipi-redis
|
||||
image: redis:alpine
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./data/redis:/data
|
||||
healthcheck:
|
||||
test: ['CMD', 'redis-cli', 'ping']
|
||||
interval: 5s
|
||||
timeout: 10s
|
||||
retries: 120
|
||||
networks:
|
||||
- tipi_main_network
|
||||
|
||||
dashboard:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
restart: unless-stopped
|
||||
container_name: dashboard
|
||||
networks:
|
||||
- tipi_main_network
|
||||
depends_on:
|
||||
tipi-db:
|
||||
condition: service_healthy
|
||||
tipi-redis:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
INTERNAL_IP: ${INTERNAL_IP}
|
||||
TIPI_VERSION: ${TIPI_VERSION}
|
||||
JWT_SECRET: ${JWT_SECRET}
|
||||
NGINX_PORT: ${NGINX_PORT}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
POSTGRES_USERNAME: ${POSTGRES_USERNAME}
|
||||
POSTGRES_DBNAME: ${POSTGRES_DBNAME}
|
||||
POSTGRES_HOST: ${POSTGRES_HOST}
|
||||
APPS_REPO_ID: ${APPS_REPO_ID}
|
||||
APPS_REPO_URL: ${APPS_REPO_URL}
|
||||
DOMAIN: ${DOMAIN}
|
||||
ARCHITECTURE: ${ARCHITECTURE}
|
||||
REDIS_HOST: ${REDIS_HOST}
|
||||
DEMO_MODE: ${DEMO_MODE}
|
||||
volumes:
|
||||
- ${PWD}/state:/runtipi/state
|
||||
- ${PWD}/repos:/runtipi/repos:ro
|
||||
- ${PWD}/apps:/runtipi/apps
|
||||
- ${PWD}/logs:/app/logs
|
||||
- ${PWD}:/app/storage
|
||||
labels:
|
||||
traefik.enable: true
|
||||
# Web
|
||||
traefik.http.routers.dashboard.rule: PathPrefix("/")
|
||||
traefik.http.routers.dashboard.service: dashboard
|
||||
traefik.http.routers.dashboard.entrypoints: web
|
||||
traefik.http.services.dashboard.loadbalancer.server.port: 3000
|
||||
|
||||
networks:
|
||||
tipi_main_network:
|
||||
driver: bridge
|
||||
ipam:
|
||||
driver: default
|
||||
config:
|
||||
- subnet: 10.21.21.0/24
|
|
@ -5,6 +5,8 @@
|
|||
"scripts": {
|
||||
"copy:migrations": "mkdir -p dist/migrations && cp -r ./src/server/migrations dist",
|
||||
"test": "dotenv -e .env.test -- jest --colors",
|
||||
"test:e2e": "NODE_ENV=test dotenv -e .env.e2e -- playwright test",
|
||||
"test:e2e:ui": "NODE_ENV=test dotenv -e .env.e2e -- playwright test --ui",
|
||||
"test:client": "jest --colors --selectProjects client --",
|
||||
"test:server": "jest --colors --selectProjects server --",
|
||||
"dev": "npm run copy:migrations && nodemon",
|
||||
|
@ -18,6 +20,7 @@
|
|||
"start:dev-container": "./.devcontainer/filewatcher.sh && npm run start:dev",
|
||||
"start:rc": "docker-compose -f docker-compose.rc.yml --env-file .env up --build",
|
||||
"start:prod": "docker-compose -f docker-compose.test.yml --env-file .env up --build",
|
||||
"start:e2e": "./scripts/start-e2e.sh",
|
||||
"start:pg": "docker run --name test-db -p 5433:5432 -d --rm -e POSTGRES_PASSWORD=postgres postgres:14",
|
||||
"version": "echo $npm_package_version",
|
||||
"release:rc": "./scripts/deploy/release-rc.sh",
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
ROOT_FOLDER="${PWD}"
|
||||
STATE_FOLDER="${ROOT_FOLDER}/state"
|
||||
|
||||
# Get field from json file
|
||||
function get_json_field() {
|
||||
local json_file="$1"
|
||||
|
@ -94,3 +96,145 @@ function kill_watcher() {
|
|||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function generate_env_file() {
|
||||
echo "Generating .env file..."
|
||||
env_variables=$1
|
||||
|
||||
json_file=$(mktemp)
|
||||
echo "$env_variables" > "$json_file"
|
||||
|
||||
local default_tz="Etc\/UTC"
|
||||
local tz="$(timedatectl | grep "Time zone" | awk '{print $3}' | sed 's/\//\\\//g')"
|
||||
if [[ -z "$tz" ]]; then
|
||||
tz="$default_tz"
|
||||
fi
|
||||
|
||||
local architecture="$(uname -m | tr '[:upper:]' '[:lower:]')"
|
||||
|
||||
if [[ "$architecture" == "aarch64" ]] || [[ "$architecture" == "armv8"* ]]; then
|
||||
architecture="arm64"
|
||||
elif [[ "$architecture" == "x86_64" ]]; then
|
||||
architecture="amd64"
|
||||
fi
|
||||
|
||||
# If none of the above conditions are met, the architecture is not supported
|
||||
if [[ "$architecture" != "arm64" ]] && [[ "$architecture" != "amd64" ]]; then
|
||||
echo "Architecture ${architecture} not supported if you think this is a mistake, please open an issue on GitHub."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local dns_ip=$(get_json_field "$json_file" dns_ip)
|
||||
local internal_ip=$(get_json_field "$json_file" internal_ip)
|
||||
local jwt_secret=$(get_json_field "$json_file" jwt_secret)
|
||||
local tipi_version=$(get_json_field "$json_file" tipi_version)
|
||||
local nginx_port=$(get_json_field "$json_file" nginx_port)
|
||||
local nginx_port_ssl=$(get_json_field "$json_file" nginx_port_ssl)
|
||||
local repo_id=$(get_json_field "$json_file" repo_id)
|
||||
local domain=$(get_json_field "$json_file" domain)
|
||||
local postgres_password=$(get_json_field "$json_file" postgres_password)
|
||||
local postgres_username=$(get_json_field "$json_file" postgres_username)
|
||||
local postgres_dbname=$(get_json_field "$json_file" postgres_dbname)
|
||||
local postgres_host=$(get_json_field "$json_file" postgres_host)
|
||||
local postgres_port=$(get_json_field "$json_file" postgres_port)
|
||||
local redis_host=$(get_json_field "$json_file" redis_host)
|
||||
local demo_mode=$(get_json_field "$json_file" demo_mode)
|
||||
local root_folder=$(get_json_field "$json_file" root_folder | sed 's/\//\\\//g')
|
||||
local apps_repository=$(get_json_field "$json_file" apps_repository | sed 's/\//\\\//g')
|
||||
local storage_path=$(get_json_field "$json_file" storage_path | sed 's/\//\\\//g')
|
||||
|
||||
env_file=$(mktemp)
|
||||
[[ -f "${ROOT_FOLDER}/.env" ]] && rm -f "${ROOT_FOLDER}/.env"
|
||||
[[ -f "$ROOT_FOLDER/templates/env-sample" ]] && cp "$ROOT_FOLDER/templates/env-sample" "$env_file"
|
||||
|
||||
|
||||
if [[ -f "${STATE_FOLDER}/settings.json" ]]; then
|
||||
# If dnsIp is set in settings.json, use it
|
||||
if [[ "$(get_json_field "${STATE_FOLDER}/settings.json" dnsIp)" != "null" ]]; then
|
||||
dns_ip=$(get_json_field "${STATE_FOLDER}/settings.json" dnsIp)
|
||||
fi
|
||||
|
||||
# If domain is set in settings.json, use it
|
||||
if [[ "$(get_json_field "${STATE_FOLDER}/settings.json" domain)" != "null" ]]; then
|
||||
domain=$(get_json_field "${STATE_FOLDER}/settings.json" domain)
|
||||
fi
|
||||
|
||||
# If appsRepoUrl is set in settings.json, use it
|
||||
if [[ "$(get_json_field "${STATE_FOLDER}/settings.json" appsRepoUrl)" != "null" ]]; then
|
||||
apps_repository_temp=$(get_json_field "${STATE_FOLDER}/settings.json" appsRepoUrl)
|
||||
apps_repository="$(echo "${apps_repository_temp}" | sed 's/\//\\\//g')"
|
||||
repo_id="$("${ROOT_FOLDER}"/scripts/git.sh get_hash "${apps_repository}")"
|
||||
fi
|
||||
|
||||
# If port is set in settings.json, use it
|
||||
if [[ "$(get_json_field "${STATE_FOLDER}/settings.json" port)" != "null" ]]; then
|
||||
nginx_port=$(get_json_field "${STATE_FOLDER}/settings.json" port)
|
||||
fi
|
||||
|
||||
# If sslPort is set in settings.json, use it
|
||||
if [[ "$(get_json_field "${STATE_FOLDER}/settings.json" sslPort)" != "null" ]]; then
|
||||
nginx_port_ssl=$(get_json_field "${STATE_FOLDER}/settings.json" sslPort)
|
||||
fi
|
||||
|
||||
# If listenIp is set in settings.json, use it
|
||||
if [[ "$(get_json_field "${STATE_FOLDER}/settings.json" listenIp)" != "null" ]]; then
|
||||
internal_ip=$(get_json_field "${STATE_FOLDER}/settings.json" listenIp)
|
||||
fi
|
||||
|
||||
# If demoMode is set in settings.json, use it
|
||||
if [[ "$(get_json_field "${STATE_FOLDER}/settings.json" demoMode)" == "true" ]]; then
|
||||
demo_mode="true"
|
||||
fi
|
||||
|
||||
# If storagePath is set in settings.json, use it
|
||||
storage_path_settings=$(get_json_field "${STATE_FOLDER}/settings.json" storagePath)
|
||||
if [[ "${storage_path_settings}" != "null" && "${storage_path_settings}" != "" ]]; then
|
||||
storage_path_temp="${storage_path_settings}"
|
||||
storage_path="$(echo "${storage_path_temp}" | sed 's/\//\\\//g')"
|
||||
fi
|
||||
fi
|
||||
|
||||
# If port is not 80 and domain is not tipi.localhost, we exit
|
||||
if [[ "${nginx_port}" != "80" ]] && [[ "${domain}" != "tipi.localhost" ]]; then
|
||||
echo "Using a custom domain with a custom port is not supported"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
os=$(uname)
|
||||
sed_args=(-i)
|
||||
# If os is macos, use gnu sed
|
||||
if [[ "$os" == "Darwin" ]]; then
|
||||
echo "Using gnu sed"
|
||||
sed_args=(-i '')
|
||||
fi
|
||||
|
||||
# Function below is modified from Umbrel
|
||||
# Required Notice: Copyright
|
||||
# Umbrel (https://umbrel.com)
|
||||
for template in ${env_file}; do
|
||||
sed "${sed_args[@]}" "s/<dns_ip>/${dns_ip}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<internal_ip>/${internal_ip}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<tz>/${tz}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<jwt_secret>/${jwt_secret}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<root_folder>/${root_folder}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<tipi_version>/${tipi_version}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<architecture>/${architecture}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<nginx_port>/${nginx_port}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<nginx_port_ssl>/${nginx_port_ssl}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<apps_repo_id>/${repo_id}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<apps_repo_url>/${apps_repository}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<domain>/${domain}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<storage_path>/${storage_path}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<postgres_password>/${postgres_password}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<postgres_username>/${postgres_username}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<postgres_dbname>/${postgres_dbname}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<postgres_port>/${postgres_port}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<postgres_host>/${postgres_host}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<redis_host>/${redis_host}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<demo_mode>/${demo_mode}/g" "${template}"
|
||||
done
|
||||
|
||||
mv -f "$env_file" "$ROOT_FOLDER/.env"
|
||||
chmod a+rwx "$ROOT_FOLDER/.env"
|
||||
}
|
||||
|
|
|
@ -15,57 +15,42 @@ clean_logs
|
|||
### --------------------------------
|
||||
ROOT_FOLDER="${PWD}"
|
||||
STATE_FOLDER="${ROOT_FOLDER}/state"
|
||||
SED_ROOT_FOLDER="$(echo "$ROOT_FOLDER" | sed 's/\//\\\//g')"
|
||||
NGINX_PORT=3000
|
||||
NGINX_PORT_SSL=443
|
||||
DOMAIN=tipi.localhost
|
||||
DNS_IP="9.9.9.9" # Default to Quad9 DNS
|
||||
ARCHITECTURE="$(uname -m)"
|
||||
TZ="UTC"
|
||||
JWT_SECRET=secret
|
||||
POSTGRES_PASSWORD=postgres
|
||||
POSTGRES_USERNAME=tipi
|
||||
POSTGRES_DBNAME=tipi
|
||||
POSTGRES_PORT=5432
|
||||
POSTGRES_HOST=tipi-db
|
||||
REDIS_HOST=tipi-redis
|
||||
TIPI_VERSION=$(get_json_field "${ROOT_FOLDER}/package.json" version)
|
||||
INTERNAL_IP=localhost
|
||||
DEMO_MODE=false
|
||||
storage_path="${ROOT_FOLDER}"
|
||||
STORAGE_PATH_ESCAPED="$(echo "${storage_path}" | sed 's/\//\\\//g')"
|
||||
if [[ "$ARCHITECTURE" == "aarch64" ]]; then
|
||||
ARCHITECTURE="arm64"
|
||||
elif [[ "$ARCHITECTURE" == "armv7l" ]]; then
|
||||
ARCHITECTURE="arm"
|
||||
elif [[ "$ARCHITECTURE" == "x86_64" ]]; then
|
||||
ARCHITECTURE="amd64"
|
||||
fi
|
||||
# If none of the above conditions are met, the architecture is not supported
|
||||
if [[ "$ARCHITECTURE" != "arm64" ]] && [[ "$ARCHITECTURE" != "arm" ]] && [[ "$ARCHITECTURE" != "amd64" ]]; then
|
||||
echo "Architecture not supported!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
### --------------------------------
|
||||
### Apps repository configuration
|
||||
### --------------------------------
|
||||
apps_repository="https://github.com/meienberger/runtipi-appstore"
|
||||
APPS_REPOSITORY_ESCAPED="$(echo ${apps_repository} | sed 's/\//\\\//g')"
|
||||
REPO_ID="$("${ROOT_FOLDER}"/scripts/git.sh get_hash ${apps_repository})"
|
||||
|
||||
# Override configs with settings.json
|
||||
if [[ -f "${STATE_FOLDER}/settings.json" ]]; then
|
||||
if [[ "$(get_json_field "${STATE_FOLDER}/settings.json" appsRepoUrl)" != "null" ]]; then
|
||||
apps_repository=$(get_json_field "${STATE_FOLDER}/settings.json" appsRepoUrl)
|
||||
APPS_REPOSITORY_ESCAPED="$(echo "${apps_repository}" | sed 's/\//\\\//g')"
|
||||
REPO_ID="$("${ROOT_FOLDER}"/scripts/git.sh get_hash "${apps_repository}")"
|
||||
fi
|
||||
fi
|
||||
env_variables_json=$(cat <<EOF
|
||||
{
|
||||
"dns_ip": "9.9.9.9",
|
||||
"domain": "tipi.localhost",
|
||||
"root_folder": "${ROOT_FOLDER}",
|
||||
"nginx_port": 3000,
|
||||
"nginx_port_ssl": 443,
|
||||
"jwt_secret": "secret",
|
||||
"postgres_password": "postgres",
|
||||
"postgres_username": "tipi",
|
||||
"postgres_dbname": "tipi",
|
||||
"postgres_port": 5432,
|
||||
"postgres_host": "tipi-db",
|
||||
"redis_host": "tipi-redis",
|
||||
"tipi_version": "$(get_json_field "${ROOT_FOLDER}/package.json" version)",
|
||||
"internal_ip": "localhost",
|
||||
"demo_mode": false,
|
||||
"apps_repository": "${apps_repository}",
|
||||
"storage_path": "${ROOT_FOLDER}",
|
||||
"repo_id": "$("${ROOT_FOLDER}"/scripts/git.sh get_hash "${apps_repository}")"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
|
||||
### --------------------------------
|
||||
### Watcher and system-info
|
||||
### --------------------------------
|
||||
mkdir -p "${ROOT_FOLDER}/state"
|
||||
|
||||
if [[ ! -f "${ROOT_FOLDER}/state/events" ]]; then
|
||||
touch "${ROOT_FOLDER}/state/events"
|
||||
fi
|
||||
|
@ -82,91 +67,9 @@ kill_watcher
|
|||
### --------------------------------
|
||||
### env file generation
|
||||
### --------------------------------
|
||||
ENV_FILE=$(mktemp)
|
||||
[[ -f "${ROOT_FOLDER}/.env" ]] && rm -f "${ROOT_FOLDER}/.env"
|
||||
[[ -f "$ROOT_FOLDER/templates/env-sample" ]] && cp "$ROOT_FOLDER/templates/env-sample" "$ENV_FILE"
|
||||
|
||||
OS=$(uname)
|
||||
sed_args=(-i)
|
||||
# If os is macos, use gnu sed
|
||||
if [[ "$OS" == "Darwin" ]]; then
|
||||
echo "Using gnu sed"
|
||||
sed_args=(-i '')
|
||||
fi
|
||||
|
||||
if [[ -f "${STATE_FOLDER}/settings.json" ]]; then
|
||||
# If dnsIp is set in settings.json, use it
|
||||
if [[ "$(get_json_field "${STATE_FOLDER}/settings.json" dnsIp)" != "null" ]]; then
|
||||
DNS_IP=$(get_json_field "${STATE_FOLDER}/settings.json" dnsIp)
|
||||
fi
|
||||
|
||||
# If domain is set in settings.json, use it
|
||||
if [[ "$(get_json_field "${STATE_FOLDER}/settings.json" domain)" != "null" ]]; then
|
||||
DOMAIN=$(get_json_field "${STATE_FOLDER}/settings.json" domain)
|
||||
fi
|
||||
|
||||
# If appsRepoUrl is set in settings.json, use it
|
||||
if [[ "$(get_json_field "${STATE_FOLDER}/settings.json" appsRepoUrl)" != "null" ]]; then
|
||||
apps_repository=$(get_json_field "${STATE_FOLDER}/settings.json" appsRepoUrl)
|
||||
APPS_REPOSITORY_ESCAPED="$(echo "${apps_repository}" | sed 's/\//\\\//g')"
|
||||
REPO_ID="$("${ROOT_FOLDER}"/scripts/git.sh get_hash "${apps_repository}")"
|
||||
fi
|
||||
|
||||
# If port is set in settings.json, use it
|
||||
if [[ "$(get_json_field "${STATE_FOLDER}/settings.json" port)" != "null" ]]; then
|
||||
NGINX_PORT=$(get_json_field "${STATE_FOLDER}/settings.json" port)
|
||||
fi
|
||||
|
||||
# If sslPort is set in settings.json, use it
|
||||
if [[ "$(get_json_field "${STATE_FOLDER}/settings.json" sslPort)" != "null" ]]; then
|
||||
NGINX_PORT_SSL=$(get_json_field "${STATE_FOLDER}/settings.json" sslPort)
|
||||
fi
|
||||
|
||||
# If listenIp is set in settings.json, use it
|
||||
if [[ "$(get_json_field "${STATE_FOLDER}/settings.json" listenIp)" != "null" ]]; then
|
||||
INTERNAL_IP=$(get_json_field "${STATE_FOLDER}/settings.json" listenIp)
|
||||
fi
|
||||
|
||||
# If storagePath is set in settings.json, use it
|
||||
storage_path_settings=$(get_json_field "${STATE_FOLDER}/settings.json" storagePath)
|
||||
if [[ "${storage_path_settings}" != "null" && "${storage_path_settings}" != "" ]]; then
|
||||
storage_path="${storage_path_settings}"
|
||||
STORAGE_PATH_ESCAPED="$(echo "${storage_path}" | sed 's/\//\\\//g')"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Function below is modified from Umbrel
|
||||
# Required Notice: Copyright
|
||||
# Umbrel (https://umbrel.com)
|
||||
for template in ${ENV_FILE}; do
|
||||
sed "${sed_args[@]}" "s/<dns_ip>/${DNS_IP}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<internal_ip>/${INTERNAL_IP}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<tz>/${TZ}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<jwt_secret>/${JWT_SECRET}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<root_folder>/${SED_ROOT_FOLDER}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<tipi_version>/${TIPI_VERSION}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<architecture>/${ARCHITECTURE}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<nginx_port>/${NGINX_PORT}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<nginx_port_ssl>/${NGINX_PORT_SSL}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<apps_repo_id>/${REPO_ID}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<apps_repo_url>/${APPS_REPOSITORY_ESCAPED}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<domain>/${DOMAIN}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<storage_path>/${STORAGE_PATH_ESCAPED}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<postgres_password>/${POSTGRES_PASSWORD}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<postgres_username>/${POSTGRES_USERNAME}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<postgres_dbname>/${POSTGRES_DBNAME}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<postgres_port>/${POSTGRES_PORT}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<postgres_host>/${POSTGRES_HOST}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<redis_host>/${REDIS_HOST}/g" "${template}"
|
||||
sed "${sed_args[@]}" "s/<demo_mode>/${DEMO_MODE}/g" "${template}"
|
||||
done
|
||||
|
||||
mv -f "$ENV_FILE" "$ROOT_FOLDER/.env.dev"
|
||||
cp "$ROOT_FOLDER/.env.dev" "$ROOT_FOLDER/.env"
|
||||
chmod a+rwx "$ROOT_FOLDER/.env"
|
||||
chmod a+rwx "${ROOT_FOLDER}/.env.dev"
|
||||
generate_env_file "${env_variables_json}"
|
||||
|
||||
### --------------------------------
|
||||
### Start the project
|
||||
### --------------------------------
|
||||
docker compose -f docker-compose.dev.yml --env-file "${ROOT_FOLDER}/.env.dev" up --build
|
||||
docker compose -f docker-compose.dev.yml up --build
|
||||
|
|
74
scripts/start-e2e.sh
Executable file
74
scripts/start-e2e.sh
Executable file
|
@ -0,0 +1,74 @@
|
|||
#!/usr/bin/env bash
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
if [[ "${TRACE-0}" == "1" ]]; then
|
||||
set -o xtrace
|
||||
fi
|
||||
|
||||
source "${BASH_SOURCE%/*}/common.sh"
|
||||
|
||||
clean_logs
|
||||
|
||||
### --------------------------------
|
||||
### General variables
|
||||
### --------------------------------
|
||||
ROOT_FOLDER="${PWD}"
|
||||
STATE_FOLDER="${ROOT_FOLDER}/state"
|
||||
|
||||
### --------------------------------
|
||||
### Apps repository configuration
|
||||
### --------------------------------
|
||||
apps_repository="https://github.com/meienberger/runtipi-appstore"
|
||||
|
||||
env_variables_json=$(cat <<EOF
|
||||
{
|
||||
"dns_ip": "9.9.9.9",
|
||||
"domain": "tipi.localhost",
|
||||
"root_folder": "${ROOT_FOLDER}",
|
||||
"nginx_port": 3000,
|
||||
"nginx_port_ssl": 443,
|
||||
"jwt_secret": "secret",
|
||||
"postgres_password": "postgres",
|
||||
"postgres_username": "tipi",
|
||||
"postgres_dbname": "tipi",
|
||||
"postgres_port": 5432,
|
||||
"postgres_host": "tipi-db",
|
||||
"redis_host": "tipi-redis",
|
||||
"tipi_version": "$(get_json_field "${ROOT_FOLDER}/package.json" version)",
|
||||
"internal_ip": "localhost",
|
||||
"demo_mode": false,
|
||||
"apps_repository": "${apps_repository}",
|
||||
"storage_path": "${ROOT_FOLDER}",
|
||||
"repo_id": "$("${ROOT_FOLDER}"/scripts/git.sh get_hash ${apps_repository})"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
### --------------------------------
|
||||
### Watcher and system-info
|
||||
### --------------------------------
|
||||
mkdir -p "${ROOT_FOLDER}/state"
|
||||
|
||||
if [[ ! -f "${ROOT_FOLDER}/state/events" ]]; then
|
||||
touch "${ROOT_FOLDER}/state/events"
|
||||
fi
|
||||
|
||||
if [[ ! -f "${ROOT_FOLDER}/state/system-info.json" ]]; then
|
||||
echo "{}" >"${ROOT_FOLDER}/state/system-info.json"
|
||||
fi
|
||||
|
||||
chmod -R a+rwx "${ROOT_FOLDER}/state/events"
|
||||
chmod -R a+rwx "${ROOT_FOLDER}/state/system-info.json"
|
||||
kill_watcher
|
||||
"${ROOT_FOLDER}/scripts/watcher.sh" &
|
||||
|
||||
### --------------------------------
|
||||
### env file generation
|
||||
### --------------------------------
|
||||
generate_env_file "${env_variables_json}"
|
||||
|
||||
### --------------------------------
|
||||
### Start the project
|
||||
### --------------------------------
|
||||
docker compose -f docker-compose.e2e.yml up -d --build
|
261
scripts/start.sh
261
scripts/start.sh
|
@ -33,106 +33,17 @@ fi
|
|||
### --------------------------------
|
||||
### General variables
|
||||
### --------------------------------
|
||||
DEFAULT_TZ="Etc\/UTC"
|
||||
TZ="$(timedatectl | grep "Time zone" | awk '{print $3}' | sed 's/\//\\\//g')"
|
||||
if [[ -z "$TZ" ]]; then
|
||||
TZ="$DEFAULT_TZ"
|
||||
fi
|
||||
NGINX_PORT=80
|
||||
NGINX_PORT_SSL=443
|
||||
DOMAIN=tipi.localhost
|
||||
SED_ROOT_FOLDER="$(echo "$ROOT_FOLDER" | sed 's/\//\\\//g')"
|
||||
DNS_IP="9.9.9.9" # Default to Quad9 DNS
|
||||
ARCHITECTURE="$(uname -m | tr '[:upper:]' '[:lower:]')"
|
||||
apps_repository="https://github.com/meienberger/runtipi-appstore"
|
||||
REPO_ID="$("${ROOT_FOLDER}"/scripts/git.sh get_hash ${apps_repository})"
|
||||
APPS_REPOSITORY_ESCAPED="$(echo ${apps_repository} | sed 's/\//\\\//g')"
|
||||
JWT_SECRET=$(derive_entropy "jwt")
|
||||
POSTGRES_PASSWORD=$(derive_entropy "postgres")
|
||||
POSTGRES_USERNAME=tipi
|
||||
POSTGRES_DBNAME=tipi
|
||||
POSTGRES_PORT=5432
|
||||
POSTGRES_HOST=tipi-db
|
||||
TIPI_VERSION=$(get_json_field "${ROOT_FOLDER}/package.json" version)
|
||||
storage_path="${ROOT_FOLDER}"
|
||||
STORAGE_PATH_ESCAPED="$(echo "${storage_path}" | sed 's/\//\\\//g')"
|
||||
REDIS_HOST=tipi-redis
|
||||
DEMO_MODE=false
|
||||
INTERNAL_IP=
|
||||
|
||||
if [[ "$ARCHITECTURE" == "aarch64" ]] || [[ "$ARCHITECTURE" == "armv8"* ]]; then
|
||||
ARCHITECTURE="arm64"
|
||||
elif [[ "$ARCHITECTURE" == "x86_64" ]]; then
|
||||
ARCHITECTURE="amd64"
|
||||
|
||||
if [[ -f "${STATE_FOLDER}/settings.json" ]]; then
|
||||
# If listenIp is set in settings.json, use it
|
||||
if [[ "$(get_json_field "${STATE_FOLDER}/settings.json" listenIp)" != "null" ]]; then
|
||||
INTERNAL_IP=$(get_json_field "${STATE_FOLDER}/settings.json" listenIp)
|
||||
fi
|
||||
fi
|
||||
|
||||
# If none of the above conditions are met, the architecture is not supported
|
||||
if [[ "$ARCHITECTURE" != "arm64" ]] && [[ "$ARCHITECTURE" != "amd64" ]]; then
|
||||
echo "Architecture ${ARCHITECTURE} not supported if you think this is a mistake, please open an issue on GitHub."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
### --------------------------------
|
||||
### CLI arguments
|
||||
### --------------------------------
|
||||
while [ -n "${1-}" ]; do
|
||||
case "$1" in
|
||||
--rc) rc="true" ;;
|
||||
--ci) ci="true" ;;
|
||||
--demo) DEMO_MODE=true ;;
|
||||
--port)
|
||||
port="${2-}"
|
||||
|
||||
if [[ "${port}" =~ ^[0-9]+$ ]]; then
|
||||
NGINX_PORT="${port}"
|
||||
else
|
||||
echo "--port must be a number"
|
||||
exit 1
|
||||
fi
|
||||
shift
|
||||
;;
|
||||
--ssl-port)
|
||||
ssl_port="${2-}"
|
||||
|
||||
if [[ "${ssl_port}" =~ ^[0-9]+$ ]]; then
|
||||
NGINX_PORT_SSL="${ssl_port}"
|
||||
else
|
||||
echo "--ssl-port must be a number"
|
||||
exit 1
|
||||
fi
|
||||
shift
|
||||
;;
|
||||
--domain)
|
||||
domain="${2-}"
|
||||
|
||||
if [[ "${domain}" =~ ^[a-zA-Z0-9.-]+$ ]]; then
|
||||
DOMAIN="${domain}"
|
||||
else
|
||||
echo "--domain must be a valid domain"
|
||||
exit 1
|
||||
fi
|
||||
shift
|
||||
;;
|
||||
--listen-ip)
|
||||
listen_ip="${2-}"
|
||||
|
||||
if [[ "${listen_ip}" =~ ^[a-fA-F0-9.:]+$ ]]; then
|
||||
INTERNAL_IP="${listen_ip}"
|
||||
else
|
||||
echo "--listen-ip must be a valid IP address"
|
||||
exit 1
|
||||
fi
|
||||
shift
|
||||
;;
|
||||
--)
|
||||
shift # The double dash makes them parameters
|
||||
break
|
||||
;;
|
||||
*) echo "Option $1 not recognized" && exit 1 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [[ -z "${INTERNAL_IP:-}" ]]; then
|
||||
network_interface="$(ip route | grep default | awk '{print $5}' | uniq)"
|
||||
network_interface_count=$(echo "$network_interface" | wc -l)
|
||||
|
@ -175,11 +86,33 @@ if [[ -z "${INTERNAL_IP:-}" ]]; then
|
|||
fi
|
||||
fi
|
||||
|
||||
# If port is not 80 and domain is not tipi.localhost, we exit
|
||||
if [[ "${NGINX_PORT}" != "80" ]] && [[ "${DOMAIN}" != "tipi.localhost" ]]; then
|
||||
echo "Using a custom domain with a custom port is not supported"
|
||||
exit 1
|
||||
fi
|
||||
env_variables_json=$(cat <<EOF
|
||||
{
|
||||
"dns_ip": "9.9.9.9",
|
||||
"internal_ip": "${INTERNAL_IP}",
|
||||
"jwt_secret": "$(derive_entropy "jwt")",
|
||||
"root_folder": "${ROOT_FOLDER}",
|
||||
"tipi_version": "$(get_json_field "${ROOT_FOLDER}/package.json" version)",
|
||||
"nginx_port": 80,
|
||||
"nginx_port_ssl": 443,
|
||||
"postgres_password": "$(derive_entropy "postgres")
|
||||
"postgres_username": "tipi",
|
||||
"postgres_dbname": "tipi",
|
||||
"postgres_port": 5432,
|
||||
"postgres_host": "tipi-db",
|
||||
"redis_host": "tipi-redis",
|
||||
"repo_id": "$("${ROOT_FOLDER}"/scripts/git.sh get_hash "${apps_repository}")",
|
||||
"apps_repository": "${apps_repository}",
|
||||
"domain": "tipi.localhost",
|
||||
"storage_path": "${ROOT_FOLDER}",
|
||||
"demo_mode": false,
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
echo "Generating config files..."
|
||||
write_log "Final values: \n${env_variables_json}"
|
||||
generate_env_file "${env_variables_json}"
|
||||
|
||||
### --------------------------------
|
||||
### Watcher and system-info
|
||||
|
@ -190,117 +123,24 @@ echo "Running system-info.sh..."
|
|||
kill_watcher
|
||||
"${ROOT_FOLDER}/scripts/watcher.sh" &
|
||||
|
||||
### --------------------------------
|
||||
### settings.json overrides
|
||||
### --------------------------------
|
||||
echo "Generating config files..."
|
||||
# Override vars with values from settings.json
|
||||
if [[ -f "${STATE_FOLDER}/settings.json" ]]; then
|
||||
|
||||
# If dnsIp is set in settings.json, use it
|
||||
if [[ "$(get_json_field "${STATE_FOLDER}/settings.json" dnsIp)" != "null" ]]; then
|
||||
DNS_IP=$(get_json_field "${STATE_FOLDER}/settings.json" dnsIp)
|
||||
fi
|
||||
|
||||
# If domain is set in settings.json, use it
|
||||
if [[ "$(get_json_field "${STATE_FOLDER}/settings.json" domain)" != "null" ]]; then
|
||||
DOMAIN=$(get_json_field "${STATE_FOLDER}/settings.json" domain)
|
||||
fi
|
||||
|
||||
# If appsRepoUrl is set in settings.json, use it
|
||||
if [[ "$(get_json_field "${STATE_FOLDER}/settings.json" appsRepoUrl)" != "null" ]]; then
|
||||
apps_repository=$(get_json_field "${STATE_FOLDER}/settings.json" appsRepoUrl)
|
||||
APPS_REPOSITORY_ESCAPED="$(echo "${apps_repository}" | sed 's/\//\\\//g')"
|
||||
REPO_ID="$("${ROOT_FOLDER}"/scripts/git.sh get_hash "${apps_repository}")"
|
||||
fi
|
||||
|
||||
# If port is set in settings.json, use it
|
||||
if [[ "$(get_json_field "${STATE_FOLDER}/settings.json" port)" != "null" ]]; then
|
||||
NGINX_PORT=$(get_json_field "${STATE_FOLDER}/settings.json" port)
|
||||
fi
|
||||
|
||||
# If sslPort is set in settings.json, use it
|
||||
if [[ "$(get_json_field "${STATE_FOLDER}/settings.json" sslPort)" != "null" ]]; then
|
||||
NGINX_PORT_SSL=$(get_json_field "${STATE_FOLDER}/settings.json" sslPort)
|
||||
fi
|
||||
|
||||
# If listenIp is set in settings.json, use it
|
||||
if [[ "$(get_json_field "${STATE_FOLDER}/settings.json" listenIp)" != "null" ]]; then
|
||||
INTERNAL_IP=$(get_json_field "${STATE_FOLDER}/settings.json" listenIp)
|
||||
fi
|
||||
|
||||
# If demoMode is set in settings.json, use it
|
||||
if [[ "$(get_json_field "${STATE_FOLDER}/settings.json" demoMode)" == "true" ]]; then
|
||||
DEMO_MODE="true"
|
||||
fi
|
||||
|
||||
# If storagePath is set in settings.json, use it
|
||||
storage_path_settings=$(get_json_field "${STATE_FOLDER}/settings.json" storagePath)
|
||||
if [[ "${storage_path_settings}" != "null" && "${storage_path_settings}" != "" ]]; then
|
||||
storage_path="${storage_path_settings}"
|
||||
STORAGE_PATH_ESCAPED="$(echo "${storage_path}" | sed 's/\//\\\//g')"
|
||||
fi
|
||||
fi
|
||||
|
||||
new_values="DOMAIN=${DOMAIN}\nDNS_IP=${DNS_IP}\nAPPS_REPOSITORY=${APPS_REPOSITORY_ESCAPED}\nREPO_ID=${REPO_ID}\nNGINX_PORT=${NGINX_PORT}\nNGINX_PORT_SSL=${NGINX_PORT_SSL}\nINTERNAL_IP=${INTERNAL_IP}\nSTORAGE_PATH=${STORAGE_PATH_ESCAPED}\nTZ=${TZ}\nJWT_SECRET=${JWT_SECRET}\nROOT_FOLDER=${SED_ROOT_FOLDER}\nTIPI_VERSION=${TIPI_VERSION}\nARCHITECTURE=${ARCHITECTURE}"
|
||||
write_log "Final values: \n${new_values}"
|
||||
|
||||
### --------------------------------
|
||||
### env file generation
|
||||
### --------------------------------
|
||||
ENV_FILE=$(mktemp)
|
||||
[[ -f "${ROOT_FOLDER}/.env" ]] && rm -f "${ROOT_FOLDER}/.env"
|
||||
[[ -f "$ROOT_FOLDER/templates/env-sample" ]] && cp "$ROOT_FOLDER/templates/env-sample" "$ENV_FILE"
|
||||
|
||||
|
||||
# Function below is modified from Umbrel
|
||||
# Required Notice: Copyright
|
||||
# Umbrel (https://umbrel.com)
|
||||
for template in ${ENV_FILE}; do
|
||||
sed -i "s/<dns_ip>/${DNS_IP}/g" "${template}"
|
||||
sed -i "s/<internal_ip>/${INTERNAL_IP}/g" "${template}"
|
||||
sed -i "s/<tz>/${TZ}/g" "${template}"
|
||||
sed -i "s/<jwt_secret>/${JWT_SECRET}/g" "${template}"
|
||||
sed -i "s/<root_folder>/${SED_ROOT_FOLDER}/g" "${template}"
|
||||
sed -i "s/<tipi_version>/${TIPI_VERSION}/g" "${template}"
|
||||
sed -i "s/<architecture>/${ARCHITECTURE}/g" "${template}"
|
||||
sed -i "s/<nginx_port>/${NGINX_PORT}/g" "${template}"
|
||||
sed -i "s/<nginx_port_ssl>/${NGINX_PORT_SSL}/g" "${template}"
|
||||
sed -i "s/<postgres_password>/${POSTGRES_PASSWORD}/g" "${template}"
|
||||
sed -i "s/<postgres_username>/${POSTGRES_USERNAME}/g" "${template}"
|
||||
sed -i "s/<postgres_dbname>/${POSTGRES_DBNAME}/g" "${template}"
|
||||
sed -i "s/<postgres_port>/${POSTGRES_PORT}/g" "${template}"
|
||||
sed -i "s/<postgres_host>/${POSTGRES_HOST}/g" "${template}"
|
||||
sed -i "s/<apps_repo_id>/${REPO_ID}/g" "${template}"
|
||||
sed -i "s/<apps_repo_url>/${APPS_REPOSITORY_ESCAPED}/g" "${template}"
|
||||
sed -i "s/<domain>/${DOMAIN}/g" "${template}"
|
||||
sed -i "s/<storage_path>/${STORAGE_PATH_ESCAPED}/g" "${template}"
|
||||
sed -i "s/<redis_host>/${REDIS_HOST}/g" "${template}"
|
||||
sed -i "s/<demo_mode>/${DEMO_MODE}/g" "${template}"
|
||||
done
|
||||
|
||||
mv -f "$ENV_FILE" "$ROOT_FOLDER/.env"
|
||||
|
||||
### --------------------------------
|
||||
### Start the project
|
||||
### --------------------------------
|
||||
if [[ ! "${ci-false}" == "true" ]]; then
|
||||
|
||||
if [[ "${rc-false}" == "true" ]]; then
|
||||
docker compose -f docker-compose.rc.yml --env-file "${ROOT_FOLDER}/.env" pull
|
||||
# Run docker compose
|
||||
docker compose -f docker-compose.rc.yml --env-file "${ROOT_FOLDER}/.env" up --detach --remove-orphans --build || {
|
||||
echo "Failed to start containers"
|
||||
exit 1
|
||||
}
|
||||
else
|
||||
docker compose --env-file "${ROOT_FOLDER}/.env" pull
|
||||
# Run docker compose
|
||||
docker compose --env-file "${ROOT_FOLDER}/.env" up --detach --remove-orphans --build || {
|
||||
echo "Failed to start containers"
|
||||
exit 1
|
||||
}
|
||||
fi
|
||||
if [[ "${rc-false}" == "true" ]]; then
|
||||
docker compose -f docker-compose.rc.yml --env-file "${ROOT_FOLDER}/.env" pull
|
||||
# Run docker compose
|
||||
docker compose -f docker-compose.rc.yml --env-file "${ROOT_FOLDER}/.env" up --detach --remove-orphans --build || {
|
||||
echo "Failed to start containers"
|
||||
exit 1
|
||||
}
|
||||
else
|
||||
docker compose --env-file "${ROOT_FOLDER}/.env" pull
|
||||
# Run docker compose
|
||||
docker compose --env-file "${ROOT_FOLDER}/.env" up --detach --remove-orphans --build || {
|
||||
echo "Failed to start containers"
|
||||
exit 1
|
||||
}
|
||||
fi
|
||||
|
||||
echo "Tipi is now running"
|
||||
|
@ -328,11 +168,6 @@ cat <<"EOF"
|
|||
()`
|
||||
EOF
|
||||
|
||||
port_display=""
|
||||
if [[ $NGINX_PORT != "80" ]]; then
|
||||
port_display=":${NGINX_PORT}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Visit http://${INTERNAL_IP}${port_display}/ to view the dashboard"
|
||||
echo "Visit http://${INTERNAL_IP}/ to view the dashboard"
|
||||
echo ""
|
||||
|
|
Loading…
Reference in a new issue