Skip to content

Commit

Permalink
refactor: streamline seafile-seafile.sh script for improved readabili…
Browse files Browse the repository at this point in the history
…ty and functionality
  • Loading branch information
MahdiBaghbani committed Jan 23, 2025
1 parent ff0a402 commit ee7db23
Showing 1 changed file with 136 additions and 243 deletions.
379 changes: 136 additions & 243 deletions dev/ocm-test-suite/share-with/seafile-seafile.sh
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 "$@"

0 comments on commit ee7db23

Please sign in to comment.