-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: streamline seafile-seafile.sh script for improved readabili…
…ty and functionality
- Loading branch information
1 parent
ff0a402
commit ee7db23
Showing
1 changed file
with
136 additions
and
243 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,252 +1,145 @@ | ||
#!/usr/bin/env bash | ||
|
||
# @michielbdejong halt on error in docker init scripts. | ||
set -e | ||
|
||
# find this scripts location. | ||
SOURCE=${BASH_SOURCE[0]} | ||
while [ -L "${SOURCE}" ]; do # resolve "${SOURCE}" until the file is no longer a symlink. | ||
DIR=$( cd -P "$( dirname "${SOURCE}" )" >/dev/null 2>&1 && pwd ) | ||
SOURCE=$(readlink "${SOURCE}") | ||
# if "${SOURCE}" was a relative symlink, we need to resolve it relative to the path where the symlink file was located. | ||
[[ "${SOURCE}" != /* ]] && SOURCE="${DIR}/${SOURCE}" | ||
done | ||
DIR=$( cd -P "$( dirname "${SOURCE}" )" >/dev/null 2>&1 && pwd ) | ||
|
||
cd "${DIR}/../../.." || exit | ||
|
||
ENV_ROOT=$(pwd) | ||
export ENV_ROOT=${ENV_ROOT} | ||
|
||
# seafile version: | ||
# - 8.0.8 | ||
# - 9.0.10 | ||
# - 10.0.1 | ||
# - 11.0.5 | ||
EFSS_PLATFORM_1_VERSION=${1:-"11.0.5"} | ||
|
||
# seafile version: | ||
# - 8.0.8 | ||
# - 9.0.10 | ||
# - 10.0.1 | ||
# - 11.0.5 | ||
EFSS_PLATFORM_2_VERSION=${2:-"11.0.5"} | ||
|
||
# script mode: dev, ci. default is dev. | ||
SCRIPT_MODE=${3:-"dev"} | ||
|
||
# browser platform: chrome, edge, firefox, electron. default is electron. | ||
# only applies on SCRIPT_MODE=ci | ||
BROWSER_PLATFORM=${4:-"electron"} | ||
|
||
function redirect_to_null_cmd() { | ||
if [ "${SCRIPT_MODE}" = "ci" ]; then | ||
"$@" >/dev/null 2>&1 | ||
else | ||
"$@" | ||
fi | ||
# ----------------------------------------------------------------------------------- | ||
# Script to Test Seafile-to-Seafile share-with flow tests. | ||
# Author: Mohammad Mahdi Baghbani Pourvahid <[email protected]> | ||
# ----------------------------------------------------------------------------------- | ||
|
||
# ----------------------------------------------------------------------------------- | ||
# Description: | ||
# This script automates the setup and testing of Seafile-to-Seafile sharing using | ||
# Cypress and Docker containers. It supports both development and CI environments. | ||
|
||
# Usage: | ||
# ./seafile-seafile.sh [EFSS_PLATFORM_1_VERSION] [EFSS_PLATFORM_2_VERSION] [SCRIPT_MODE] [BROWSER_PLATFORM] | ||
|
||
# Arguments: | ||
# EFSS_PLATFORM_1_VERSION : Version of the first Seafile instance (default: "v11.0.5"). | ||
# EFSS_PLATFORM_2_VERSION : Version of the second Seafile instance (default: "v11.0.5"). | ||
# SCRIPT_MODE : Script mode (default: "dev"). Options: dev, ci. | ||
# BROWSER_PLATFORM : Browser platform (default: "electron"). Options: chrome, edge, firefox, electron. | ||
|
||
# Example: | ||
# ./seafile-seafile.sh v11.0.5 v11.0.5 ci electron | ||
|
||
# ----------------------------------------------------------------------------------- | ||
|
||
# Exit immediately if a command exits with a non-zero status, | ||
# a variable is used but not defined, or a command in a pipeline fails | ||
set -euo pipefail | ||
|
||
# ----------------------------------------------------------------------------------- | ||
# Constants and Default Values | ||
# ----------------------------------------------------------------------------------- | ||
|
||
# Default versions | ||
DEFAULT_EFSS_1_VERSION="v11.0.5" | ||
DEFAULT_EFSS_2_VERSION="v11.0.5" | ||
|
||
# ----------------------------------------------------------------------------------- | ||
# Function: resolve_script_dir | ||
# Purpose : Resolves the absolute path of the script's directory, handling symlinks. | ||
# Returns : | ||
# Exports SOURCE, SCRIPT_DIR | ||
# Note : This function relies on BASH_SOURCE, so it must be used in a Bash shell. | ||
# ----------------------------------------------------------------------------------- | ||
resolve_script_dir() { | ||
local source="${BASH_SOURCE[0]}" | ||
|
||
# Follow symbolic links until we get the real file location | ||
while [ -L "${source}" ]; do | ||
# Get the directory path where the symlink is located | ||
dir="$(cd -P "$(dirname "${source}")" >/dev/null 2>&1 && pwd)" | ||
# Use readlink to get the target the symlink points to | ||
source="$(readlink "${source}")" | ||
# If the source was a relative symlink, convert it to an absolute path | ||
[[ "${source}" != /* ]] && source="${dir}/${source}" | ||
done | ||
|
||
# After resolving symlinks, retrieve the directory of the final source | ||
SCRIPT_DIR="$(cd -P "$(dirname "${source}")" >/dev/null 2>&1 && pwd)" | ||
|
||
# Exports | ||
export SOURCE="${source}" | ||
export SCRIPT_DIR="${SCRIPT_DIR}" | ||
} | ||
|
||
function waitForPort () { | ||
redirect_to_null_cmd echo waitForPort "${1} ${2}" | ||
# the "| cat" after the "| grep" is to prevent the command from exiting with 1 if no match is found by grep. | ||
x=$(docker exec "${1}" ss -tulpn | grep -c "${2}" | cat) | ||
until [ "${x}" -ne 0 ] | ||
do | ||
redirect_to_null_cmd echo Waiting for "${1} to open port ${2}, this usually takes about 10 seconds ... ${x}" | ||
sleep 1 | ||
x=$(docker exec "${1}" ss -tulpn | grep -c "${2}" | cat) | ||
done | ||
redirect_to_null_cmd echo "${1} port ${2} is open" | ||
} | ||
# ----------------------------------------------------------------------------------- | ||
# Function: initialize_environment | ||
# Purpose : | ||
# 1) Resolve the script's directory. | ||
# 2) Change into that directory plus an optional subdirectory (if provided). | ||
# 3) Export ENV_ROOT as the new working directory. | ||
# 4) Source a utility script (`utils.sh`) with optional version parameters. | ||
# | ||
# Arguments: | ||
# 1) $1 - Relative or absolute path to a subdirectory (optional). | ||
# If omitted or empty, defaults to '.' (the same directory as resolve_script_dir). | ||
# | ||
# Usage Example: | ||
# initialize_environment # Uses the script's directory | ||
# initialize_environment "dev" # Changes to script's directory + "/dev" | ||
# ----------------------------------------------------------------------------------- | ||
initialize_environment() { | ||
# Resolve script's directory | ||
resolve_script_dir | ||
|
||
# Local variables | ||
local subdir | ||
# Check if a subdirectory argument was passed; default to '.' if not | ||
subdir="${1:-.}" | ||
|
||
# Attempt to change into the resolved directory + the subdirectory | ||
if cd "${SCRIPT_DIR}/${subdir}"; then | ||
ENV_ROOT="$(pwd)" | ||
export ENV_ROOT | ||
else | ||
printf "Error: %s\n" "Failed to change directory to '${SCRIPT_DIR}/${subdir}'." >&2 && exit 1 | ||
fi | ||
|
||
function waitForCollabora() { | ||
x=$(docker logs collabora.docker | grep -c "Ready") | ||
until [ "${x}" -ne 0 ] | ||
do | ||
redirect_to_null_cmd echo "Waiting for Collabora to be ready, this usually takes about 10 seconds ... ${x}" | ||
sleep 1 | ||
x=$(docker logs collabora.docker | grep -c "Ready") | ||
done | ||
redirect_to_null_cmd echo "Collabora is ready" | ||
# shellcheck source=/dev/null | ||
# Source utility script (assuming it exists and is required for subsequent commands) | ||
if [[ -f "${ENV_ROOT}/scripts/utils.sh" ]]; then | ||
source "${ENV_ROOT}/scripts/utils.sh" "${DEFAULT_EFSS_1_VERSION}" "${DEFAULT_EFSS_2_VERSION}" | ||
else | ||
printf "Error: %s\n" "Could not source '${ENV_ROOT}/scripts/utils.sh' (file not found)." >&2 && exit 1 | ||
fi | ||
} | ||
|
||
function createEfssSeafile() { | ||
local platform="${1}" | ||
local number="${2}" | ||
local user_email="${3}" | ||
local password="${4}" | ||
local remote_ocm_server="${5}" | ||
local tag="${6-latest}" | ||
|
||
redirect_to_null_cmd echo "creating efss ${platform} ${number}" | ||
|
||
redirect_to_null_cmd docker run --detach --network=testnet \ | ||
--name="memcache${platform}${number}.docker" \ | ||
memcached:1.6.18 \ | ||
memcached -m 256 | ||
|
||
redirect_to_null_cmd docker run --detach --network=testnet \ | ||
--name="maria${platform}${number}.docker" \ | ||
-e MARIADB_ROOT_PASSWORD=eilohtho9oTahsuongeeTh7reedahPo1Ohwi3aek \ | ||
mariadb:11.4.2 \ | ||
--transaction-isolation=READ-COMMITTED \ | ||
--binlog-format=ROW \ | ||
--innodb-file-per-table=1 \ | ||
--skip-innodb-read-only-compressed | ||
|
||
redirect_to_null_cmd docker run --detach --network=testnet \ | ||
--name="${platform}${number}.docker" \ | ||
-e TIME_ZONE="Etc/UTC" \ | ||
-e DB_HOST="maria${platform}${number}.docker" \ | ||
-e DB_ROOT_PASSWD="eilohtho9oTahsuongeeTh7reedahPo1Ohwi3aek" \ | ||
-e SEAFILE_ADMIN_EMAIL="${user_email}" \ | ||
-e SEAFILE_ADMIN_PASSWORD="${password}" \ | ||
-e SEAFILE_SERVER_LETSENCRYPT=false \ | ||
-e FORCE_HTTPS_IN_CONF=false \ | ||
-e SEAFILE_SERVER_HOSTNAME="${platform}${number}.docker" \ | ||
-e SEAFILE_MEMCACHE_HOST="memcache${platform}${number}.docker" \ | ||
-e SEAFILE_MEMCACHE_PORT=11211 \ | ||
-v "${ENV_ROOT}/temp/sea-init.sh:/init.sh" \ | ||
-v "${ENV_ROOT}/temp/seafile-data/${platform}${number}:/shared" \ | ||
-v "${ENV_ROOT}/docker/tls/certificates/${platform}${number}.crt:/shared/ssl/${platform}${number}.docker.crt" \ | ||
-v "${ENV_ROOT}/docker/tls/certificates/${platform}${number}.key:/shared/ssl/${platform}${number}.docker.key" \ | ||
-v "${ENV_ROOT}/docker/tls/certificates:/certificates" \ | ||
-v "${ENV_ROOT}/docker/tls/certificate-authority:/certificate-authority" \ | ||
"seafileltd/seafile-mc:${tag}" | ||
|
||
# wait for hostname port to be open. | ||
waitForPort "maria${platform}${number}.docker" 3306 | ||
|
||
# add self-signed certificates to os and trust them. (use >/dev/null 2>&1 to shut these up) | ||
docker exec "${platform}${number}.docker" bash -c "cp -f /certificates/*.crt /usr/local/share/ca-certificates/ || true" >/dev/null 2>&1 | ||
docker exec "${platform}${number}.docker" bash -c "cp -f /certificate-authority/*.crt /usr/local/share/ca-certificates/ || true" >/dev/null 2>&1 | ||
docker exec "${platform}${number}.docker" update-ca-certificates >/dev/null 2>&1 | ||
|
||
# seafile needs time to bootstrap itself. | ||
sleep 5 | ||
|
||
# run init script inside seafile. | ||
redirect_to_null_cmd docker exec -e remote_ocm_server="${remote_ocm_server}" "${platform}${number}.docker" bash -c "/init.sh ${remote_ocm_server}" | ||
|
||
# restart seafile to apply our changes. | ||
sleep 2 | ||
redirect_to_null_cmd docker restart "${platform}${number}.docker" | ||
sleep 2 | ||
|
||
redirect_to_null_cmd echo "" | ||
# ----------------------------------------------------------------------------------- | ||
# Main Execution | ||
# Purpose : | ||
# 1) Initialize the environment | ||
# 2) Parse CLI arguments and validate necessary files | ||
# 3) Prepare environment (clean up, create Docker network, etc.) | ||
# 4) Create EFSS containers | ||
# 5) Run dev or CI mode depending on SCRIPT_MODE | ||
# | ||
# Arguments: | ||
# All command line arguments are passed to parse_arguments. | ||
# | ||
# Returns : None - the script will exit upon errors (via error_exit) or complete normally. | ||
# ----------------------------------------------------------------------------------- | ||
main() { | ||
# Initialize environment and parse arguments | ||
initialize_environment "../../.." | ||
setup "$@" | ||
|
||
# Create EFSS containers | ||
# # id # username # password # image # tag # remote_ocm_server | ||
create_seafile 1 "[email protected]" "xu" seafileltd/seafile-mc "${EFSS_PLATFORM_1_VERSION}" "seafile2" | ||
create_seafile 2 "[email protected]" "lopresti" seafileltd/seafile-mc "${EFSS_PLATFORM_2_VERSION}" "seafile1" | ||
|
||
if [ "${SCRIPT_MODE}" = "dev" ]; then | ||
run_dev \ | ||
"https://seafile1.docker (username: [email protected], password: xu)" \ | ||
"https://seafile2.docker (username: [email protected], password: lopresti)" | ||
else | ||
run_ci "${TEST_SCENARIO}" "${EFSS_PLATFORM_1}" "${EFSS_PLATFORM_2}" | ||
fi | ||
} | ||
|
||
# delete and create temp directory. | ||
rm -rf "${ENV_ROOT}/temp" && mkdir -p "${ENV_ROOT}/temp" | ||
|
||
# copy init files. | ||
cp -f "${ENV_ROOT}/docker/scripts/init/seafile.sh" "${ENV_ROOT}/temp/sea-init.sh" | ||
|
||
# auto clean before starting. | ||
"${ENV_ROOT}/scripts/clean.sh" "no" | ||
|
||
# make sure network exists. | ||
docker network inspect testnet >/dev/null 2>&1 || docker network create testnet >/dev/null 2>&1 | ||
|
||
|
||
############### | ||
### Seafile ### | ||
############### | ||
|
||
# Seafiles. | ||
createEfssSeafile seafile 1 [email protected] xu seafile2 "${EFSS_PLATFORM_1_VERSION}" | ||
createEfssSeafile seafile 2 [email protected] lopresti seafile1 "${EFSS_PLATFORM_2_VERSION}" | ||
|
||
if [ "${SCRIPT_MODE}" = "dev" ]; then | ||
############### | ||
### Firefox ### | ||
############### | ||
|
||
docker run --detach --network=testnet \ | ||
--name=firefox \ | ||
-p 5800:5800 \ | ||
--shm-size 2g \ | ||
-e USER_ID="${UID}" \ | ||
-e GROUP_ID="${UID}" \ | ||
-e DARK_MODE=1 \ | ||
-v "${ENV_ROOT}/docker/tls/browsers/firefox/cert9.db:/config/profile/cert9.db:rw" \ | ||
-v "${ENV_ROOT}/docker/tls/browsers/firefox/cert_override.txt:/config/profile/cert_override.txt:rw" \ | ||
jlesage/firefox:latest \ | ||
>/dev/null 2>&1 | ||
|
||
################## | ||
### VNC Server ### | ||
################## | ||
|
||
# remove previous x11 unix socket file, avoid any problems while mounting new one. | ||
sudo rm -rf "${ENV_ROOT}/temp/.X11-unix" | ||
|
||
# try to change DISPLAY_WIDTH, DISPLAY_HEIGHT to make it fit in your screen, | ||
# NOTE: please do not commit any change related to resolution. | ||
docker run --detach --network=testnet \ | ||
--name=vnc-server \ | ||
-p 5700:8080 \ | ||
-e RUN_XTERM=no \ | ||
-e DISPLAY_WIDTH=1920 \ | ||
-e DISPLAY_HEIGHT=1080 \ | ||
-v "${ENV_ROOT}/temp/.X11-unix:/tmp/.X11-unix" \ | ||
theasp/novnc:latest | ||
|
||
############### | ||
### Cypress ### | ||
############### | ||
|
||
# create cypress and attach its display to the VNC server container. | ||
# this way you can view inside cypress container through vnc server. | ||
docker run --detach --network=testnet \ | ||
--name="cypress.docker" \ | ||
-e DISPLAY=vnc-server:0.0 \ | ||
-v "${ENV_ROOT}/cypress/ocm-test-suite:/ocm" \ | ||
-v "${ENV_ROOT}/temp/.X11-unix:/tmp/.X11-unix" \ | ||
-w /ocm \ | ||
--entrypoint cypress \ | ||
cypress/included:13.13.1 \ | ||
open --project . | ||
|
||
# print instructions. | ||
clear | ||
echo "Now browse to :" | ||
echo "Cypress inside VNC Server -> http://localhost:5700/vnc.html, scale VNC to get to the Continue button, and run the appropriate test from ./cypress/ocm-test-suite/cypress/e2e/" | ||
echo "Embedded Firefox -> http://localhost:5800" | ||
echo "" | ||
echo "Inside Embedded Firefox browse to EFSS hostname and enter the related credentials:" | ||
echo "https://seafile1.docker -> username: [email protected] password: xu" | ||
echo "https://seafile2.docker -> username: [email protected] password: lopresti" | ||
else | ||
# only record when testing on electron. | ||
if [ "${BROWSER_PLATFORM}" != "electron" ]; then | ||
sed -i 's/.*video: true,.*/video: false,/' "${ENV_ROOT}/cypress/ocm-test-suite/cypress.config.js" | ||
sed -i 's/.*videoCompression: true,.*/videoCompression: false,/' "${ENV_ROOT}/cypress/ocm-test-suite/cypress.config.js" | ||
fi | ||
################## | ||
### Cypress CI ### | ||
################## | ||
|
||
# extract version up until first dot . , example: v27.1.17 becomes v27 | ||
P1_VER="$( cut -d '.' -f 1 <<< "${EFSS_PLATFORM_1_VERSION}" )" | ||
P2_VER="$( cut -d '.' -f 1 <<< "${EFSS_PLATFORM_2_VERSION}" )" | ||
|
||
# run Cypress test suite headlessly and with the defined browser. | ||
docker run --network=testnet \ | ||
--name="cypress.docker" \ | ||
-v "${ENV_ROOT}/cypress/ocm-test-suite:/ocm" \ | ||
-w /ocm \ | ||
cypress/included:13.13.1 cypress run \ | ||
--browser "${BROWSER_PLATFORM}" \ | ||
--spec "cypress/e2e/share-with/seafile-${P1_VER}-to-seafile-${P2_VER}.cy.js" | ||
|
||
# revert config file back to normal. | ||
if [ "${BROWSER_PLATFORM}" != "electron" ]; then | ||
sed -i 's/.*video: false,.*/ video: true,/' "${ENV_ROOT}/cypress/ocm-test-suite/cypress.config.js" | ||
sed -i 's/.*videoCompression: false,.*/ videoCompression: true,/' "${ENV_ROOT}/cypress/ocm-test-suite/cypress.config.js" | ||
fi | ||
|
||
# auto clean after running tests in ci mode. do not clear terminal. | ||
"${ENV_ROOT}/scripts/clean.sh" "no" | ||
fi | ||
# ----------------------------------------------------------------------------------- | ||
# Execute the main function with passed arguments | ||
# ----------------------------------------------------------------------------------- | ||
main "$@" |