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
45 changes: 45 additions & 0 deletions ci/install_contentful.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/bin/bash
# Contentful CLI Installer
# npm package: contentful-cli

set -e

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m'

log_info() { echo -e "${BLUE}[Contentful CLI] $1${NC}"; }
log_ok() { echo -e "${GREEN}[Contentful CLI] $1${NC}"; }
log_warn() { echo -e "${YELLOW}[Contentful CLI] $1${NC}"; }
log_err() { echo -e "${RED}[Contentful CLI] $1${NC}"; }

check_node() {
if ! command -v node >/dev/null 2>&1; then
log_err "Node.js is required but not found. Please install Node.js LTS first."
return 1
fi
log_ok "Node.js $(node --version) detected."
}
Comment on lines +18 to +24
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

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

check_node verifies node exists, but the script later calls npm install -g ... without checking that npm is available. In some environments Node may be present without npm/npx, which would make the install fail with a less clear error. Consider explicitly checking command -v npm (and failing with a helpful message) before running the install.

Copilot uses AI. Check for mistakes.

install_contentful_cli() {
log_info "Installing Contentful CLI..."

if command -v contentful >/dev/null 2>&1; then
log_warn "Contentful CLI already installed ($(contentful --version 2>/dev/null || echo 'unknown')). Skipping."
return 0
fi

if npm install -g contentful-cli; then
log_ok "Contentful CLI installed successfully."
log_info " Run 'contentful login' to authenticate."
log_info " Docs: https://www.contentful.com/developers/docs/tutorials/cli/"
log_info " npm: https://www.npmjs.com/package/contentful-cli"
else
log_err "Failed to install Contentful CLI."
return 1
fi
}

check_node && install_contentful_cli
148 changes: 148 additions & 0 deletions ci/install_odoo.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
#!/bin/bash
# Odoo Installer
# Supports: Docker (default) or native deb/rpm package install

set -e

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m'

ODOO_VERSION="${ODOO_VERSION:-17}"
ODOO_PORT="${ODOO_PORT:-8069}"
DB_PASSWORD="${ODOO_DB_PASSWORD:-$(tr -dc A-Za-z0-9 </dev/urandom | head -c 16)}"
INSTALL_DIR="${ODOO_INSTALL_DIR:-/opt/odoo}"
Comment on lines +13 to +16
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

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

DB_PASSWORD defaults to a new random value each run. If odoo-db already exists (and you reuse it later in the script), rerunning this installer can start a new odoo container with a different PASSWORD than the existing Postgres container expects, causing connection failures. To make reruns idempotent, load the password from the persisted credentials file when it exists (or require ODOO_DB_PASSWORD when reusing an existing DB container).

Copilot uses AI. Check for mistakes.

log_info() { echo -e "${BLUE}[Odoo] $1${NC}"; }
log_ok() { echo -e "${GREEN}[Odoo] $1${NC}"; }
log_warn() { echo -e "${YELLOW}[Odoo] $1${NC}"; }
log_err() { echo -e "${RED}[Odoo] $1${NC}"; }

check_docker() {
if ! command -v docker >/dev/null 2>&1; then
log_err "Docker is not installed. Please install Docker first (the 1Panel installer handles this)."
return 1
fi
log_ok "Docker detected: $(docker --version)"
}

install_odoo_docker() {
log_info "Installing Odoo ${ODOO_VERSION} via Docker..."

if docker ps -a --format '{{.Names}}' | grep -q '^odoo$'; then
log_warn "Odoo container already exists. Skipping."
return 0
fi

# Create data directories
mkdir -p "${INSTALL_DIR}/data" "${INSTALL_DIR}/config" "${INSTALL_DIR}/addons"

# Persist credentials to a restricted file
CREDENTIALS_FILE="${INSTALL_DIR}/credentials.txt"
if [ ! -f "${CREDENTIALS_FILE}" ]; then
install -m 600 /dev/null "${CREDENTIALS_FILE}"
{
echo "Odoo DB User: odoo"
echo "Odoo DB Password: ${DB_PASSWORD}"
} > "${CREDENTIALS_FILE}"
log_info " Credentials saved to: ${CREDENTIALS_FILE}"
fi

# Create a dedicated Docker network for Odoo
if ! docker network ls --format '{{.Name}}' | grep -q '^odoo-net$'; then
log_info "Creating Docker network 'odoo-net'..."
docker network create odoo-net
fi

# Start PostgreSQL container for Odoo
if ! docker ps -a --format '{{.Names}}' | grep -q '^odoo-db$'; then
log_info "Starting PostgreSQL container for Odoo..."
docker run -d \
--name odoo-db \
--restart unless-stopped \
--network odoo-net \
-e POSTGRES_DB=postgres \
-e POSTGRES_PASSWORD="${DB_PASSWORD}" \
-e POSTGRES_USER=odoo \
-v "${INSTALL_DIR}/db:/var/lib/postgresql/data" \
postgres:15
sleep 5
else
log_warn "odoo-db container already exists, reusing."
# Ensure it is on the odoo-net network
docker network connect odoo-net odoo-db 2>/dev/null || true
fi

# Start Odoo container
log_info "Starting Odoo ${ODOO_VERSION} container on port ${ODOO_PORT}..."
docker run -d \
--name odoo \
--restart unless-stopped \
--network odoo-net \
-p "${ODOO_PORT}:8069" \
-e HOST=odoo-db \
-e USER=odoo \
-e PASSWORD="${DB_PASSWORD}" \
-v "${INSTALL_DIR}/data:/var/lib/odoo" \
-v "${INSTALL_DIR}/config:/etc/odoo" \
-v "${INSTALL_DIR}/addons:/mnt/extra-addons" \
"odoo:${ODOO_VERSION}"

log_ok "Odoo ${ODOO_VERSION} installed and running."
log_info " Access Odoo at: http://localhost:${ODOO_PORT}"
log_info " DB User: odoo | DB Password: ${DB_PASSWORD}"
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

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

The script logs the generated database password to stdout. In CI (or any environment where logs are retained/centralized) this can leak credentials. Consider omitting the password from logs (or only printing it when an explicit SHOW_CREDENTIALS=1 flag is set) and relying on the restricted credentials file instead.

Suggested change
log_info " DB User: odoo | DB Password: ${DB_PASSWORD}"
if [ "${SHOW_CREDENTIALS:-0}" = "1" ]; then
log_info " DB User: odoo | DB Password: ${DB_PASSWORD}"
else
log_info " DB User: odoo | DB Password: [hidden] (set SHOW_CREDENTIALS=1 to display)"
fi

Copilot uses AI. Check for mistakes.
log_info " Data directory: ${INSTALL_DIR}"
log_info " Docs: https://hub.docker.com/_/odoo"
}

install_odoo_package() {
log_info "Installing Odoo ${ODOO_VERSION} via system package..."

if command -v odoo >/dev/null 2>&1; then
log_warn "Odoo is already installed. Skipping."
return 0
fi

if command -v apt-get >/dev/null 2>&1; then
# Debian/Ubuntu
apt-get install -y wget gnupg
wget -q -O - https://nightly.odoo.com/odoo.key | gpg --dearmor -o /usr/share/keyrings/odoo-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/odoo-archive-keyring.gpg] https://nightly.odoo.com/${ODOO_VERSION}.0/nightly/deb/ ./" \
> /etc/apt/sources.list.d/odoo.list
apt-get update && apt-get install -y odoo
systemctl enable odoo
systemctl start odoo
elif command -v dnf >/dev/null 2>&1; then
# Fedora/RHEL/CentOS
dnf config-manager --add-repo="https://nightly.odoo.com/${ODOO_VERSION}.0/nightly/rpm/odoo.repo"
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

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

The dnf config-manager command typically comes from dnf-plugins-core; on minimal Fedora/RHEL images it may not be installed, causing this branch to fail. Consider installing the required plugin package (or detecting missing dnf config-manager and falling back to writing the repo file directly) before calling it.

Suggested change
dnf config-manager --add-repo="https://nightly.odoo.com/${ODOO_VERSION}.0/nightly/rpm/odoo.repo"
if dnf config-manager --help >/dev/null 2>&1; then
dnf config-manager --add-repo="https://nightly.odoo.com/${ODOO_VERSION}.0/nightly/rpm/odoo.repo"
else
cat >/etc/yum.repos.d/odoo.repo <<EOF
[odoo]
name=Odoo Nightly ${ODOO_VERSION}.0
baseurl=https://nightly.odoo.com/${ODOO_VERSION}.0/nightly/rpm/
enabled=1
gpgcheck=0
EOF
fi

Copilot uses AI. Check for mistakes.
dnf install -y odoo
systemctl enable odoo
systemctl start odoo
elif command -v yum >/dev/null 2>&1; then
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

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

The yum-config-manager command usually requires yum-utils to be installed; otherwise this repo-add step will fail on some systems. Consider ensuring the dependency is installed (or using an alternative method to add the repo) before invoking yum-config-manager.

Suggested change
elif command -v yum >/dev/null 2>&1; then
elif command -v yum >/dev/null 2>&1; then
if ! command -v yum-config-manager >/dev/null 2>&1; then
yum install -y yum-utils
fi

Copilot uses AI. Check for mistakes.
yum-config-manager --add-repo="https://nightly.odoo.com/${ODOO_VERSION}.0/nightly/rpm/odoo.repo"
yum install -y odoo
systemctl enable odoo
systemctl start odoo
else
log_err "Unsupported package manager. Use INSTALL_MODE=docker."
return 1
fi

log_ok "Odoo ${ODOO_VERSION} installed via system package."
log_info " Access Odoo at: http://localhost:8069"
}

main() {
log_info "Starting Odoo installation (version ${ODOO_VERSION})..."
INSTALL_MODE="${INSTALL_MODE:-docker}"

if [ "$INSTALL_MODE" = "docker" ]; then
check_docker && install_odoo_docker
else
install_odoo_package
fi
}

main
61 changes: 61 additions & 0 deletions ci/install_react_bricks.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/bin/bash
# React Bricks CMS Installer
# Scaffolds a new React Bricks project using: npx create-reactbricks-app@latest

set -e

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m'

REACTBRICKS_PROJECT_NAME="${REACTBRICKS_PROJECT_NAME:-my-reactbricks-app}"
REACTBRICKS_INSTALL_DIR="${REACTBRICKS_INSTALL_DIR:-/opt/reactbricks}"

log_info() { echo -e "${BLUE}[React Bricks] $1${NC}"; }
log_ok() { echo -e "${GREEN}[React Bricks] $1${NC}"; }
log_warn() { echo -e "${YELLOW}[React Bricks] $1${NC}"; }
log_err() { echo -e "${RED}[React Bricks] $1${NC}"; }

check_node() {
if ! command -v node >/dev/null 2>&1; then
log_err "Node.js is required but not found. Please install Node.js 18+ first."
return 1
fi
node_major=$(node --version | sed 's/v//' | cut -d. -f1)
if [ "$node_major" -lt 18 ]; then
log_err "Node.js 18+ required (found $(node --version))."
return 1
fi
log_ok "Node.js $(node --version) detected."
}

install_react_bricks() {
log_info "Setting up React Bricks CMS project '${REACTBRICKS_PROJECT_NAME}'..."

TARGET_DIR="${REACTBRICKS_INSTALL_DIR}/${REACTBRICKS_PROJECT_NAME}"

if [ -d "${TARGET_DIR}" ]; then
log_warn "React Bricks project already exists at ${TARGET_DIR}. Skipping."
return 0
fi

mkdir -p "${REACTBRICKS_INSTALL_DIR}"

log_info "Scaffolding React Bricks project at ${TARGET_DIR} (this may take a few minutes)..."
cd "${REACTBRICKS_INSTALL_DIR}"

if npx create-reactbricks-app@latest "${REACTBRICKS_PROJECT_NAME}"; then
log_ok "React Bricks project '${REACTBRICKS_PROJECT_NAME}' created at ${TARGET_DIR}."
Comment on lines +49 to +50
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

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

npx create-reactbricks-app@latest is not reproducible and may change behavior over time, which is risky for CI automation. Consider supporting a pinned version via an env var (and defaulting to a known-good version) so installs remain stable.

Copilot uses AI. Check for mistakes.
log_info " To start: cd ${TARGET_DIR} && npm run dev"
log_info " Docs: https://www.reactbricks.com/docs"
log_info " npm: https://www.npmjs.com/package/react-bricks"
log_info " Note: You will need a React Bricks account and App ID to use the CMS."
else
log_err "Failed to scaffold React Bricks project."
return 1
fi
}

check_node && install_react_bricks
50 changes: 50 additions & 0 deletions ci/install_shopify.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/bin/bash
# Shopify CLI Installer
# npm package: @shopify/cli

set -e

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m'

log_info() { echo -e "${BLUE}[Shopify CLI] $1${NC}"; }
log_ok() { echo -e "${GREEN}[Shopify CLI] $1${NC}"; }
log_warn() { echo -e "${YELLOW}[Shopify CLI] $1${NC}"; }
log_err() { echo -e "${RED}[Shopify CLI] $1${NC}"; }

check_node() {
if ! command -v node >/dev/null 2>&1; then
log_err "Node.js is required but not found. Please install Node.js 18+ first."
return 1
fi
node_major=$(node --version | sed 's/v//' | cut -d. -f1)
if [ "$node_major" -lt 18 ]; then
log_err "Node.js 18+ required (found $(node --version))."
return 1
fi
log_ok "Node.js $(node --version) detected."
}

install_shopify_cli() {
log_info "Installing Shopify CLI..."

if command -v shopify >/dev/null 2>&1; then
log_warn "Shopify CLI already installed ($(shopify version 2>/dev/null || echo 'unknown')). Skipping."
return 0
fi

if npm install -g @shopify/cli@latest; then
log_ok "Shopify CLI installed successfully."
log_info " Run 'shopify' to get started."
log_info " Docs: https://shopify.dev/docs/api/shopify-cli"
log_info " GitHub: https://github.com/Shopify/cli"
else
log_err "Failed to install Shopify CLI."
Comment on lines +32 to +45
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

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

This installs @shopify/cli@latest, which makes CI runs non-reproducible and increases supply-chain risk (a new upstream release can change behavior or break builds). Consider allowing a pinned version via an environment variable (e.g., SHOPIFY_CLI_VERSION) and defaulting to a known-good version instead of latest.

Suggested change
log_info "Installing Shopify CLI..."
if command -v shopify >/dev/null 2>&1; then
log_warn "Shopify CLI already installed ($(shopify version 2>/dev/null || echo 'unknown')). Skipping."
return 0
fi
if npm install -g @shopify/cli@latest; then
log_ok "Shopify CLI installed successfully."
log_info " Run 'shopify' to get started."
log_info " Docs: https://shopify.dev/docs/api/shopify-cli"
log_info " GitHub: https://github.com/Shopify/cli"
else
log_err "Failed to install Shopify CLI."
# Allow overriding the CLI version via SHOPIFY_CLI_VERSION; default to a pinned known-good version.
CLI_VERSION="${SHOPIFY_CLI_VERSION:-"3.69.0"}"
log_info "Installing Shopify CLI (version ${CLI_VERSION})..."
if command -v shopify >/dev/null 2>&1; then
log_warn "Shopify CLI already installed ($(shopify version 2>/dev/null || echo 'unknown')). Skipping."
return 0
fi
if npm install -g "@shopify/cli@${CLI_VERSION}"; then
log_ok "Shopify CLI installed successfully (version ${CLI_VERSION})."
log_info " Run 'shopify' to get started."
log_info " Docs: https://shopify.dev/docs/api/shopify-cli"
log_info " GitHub: https://github.com/Shopify/cli"
else
log_err "Failed to install Shopify CLI (version ${CLI_VERSION})."

Copilot uses AI. Check for mistakes.
return 1
fi
}

check_node && install_shopify_cli
62 changes: 62 additions & 0 deletions ci/install_strapi.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/bin/bash
# Strapi CMS Installer
# Scaffolds a new Strapi project using: npx create-strapi@latest

set -e

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m'

STRAPI_PROJECT_NAME="${STRAPI_PROJECT_NAME:-my-strapi-app}"
STRAPI_INSTALL_DIR="${STRAPI_INSTALL_DIR:-/opt/strapi}"

log_info() { echo -e "${BLUE}[Strapi] $1${NC}"; }
log_ok() { echo -e "${GREEN}[Strapi] $1${NC}"; }
log_warn() { echo -e "${YELLOW}[Strapi] $1${NC}"; }
log_err() { echo -e "${RED}[Strapi] $1${NC}"; }

check_node() {
if ! command -v node >/dev/null 2>&1; then
log_err "Node.js is required but not found. Please install Node.js 18+ first."
return 1
fi
node_major=$(node --version | sed 's/v//' | cut -d. -f1)
if [ "$node_major" -lt 18 ]; then
log_err "Node.js 18+ required (found $(node --version))."
return 1
fi
log_ok "Node.js $(node --version) detected."
}

install_strapi() {
log_info "Setting up Strapi CMS project '${STRAPI_PROJECT_NAME}'..."

TARGET_DIR="${STRAPI_INSTALL_DIR}/${STRAPI_PROJECT_NAME}"

if [ -d "${TARGET_DIR}" ]; then
log_warn "Strapi project already exists at ${TARGET_DIR}. Skipping."
return 0
fi

mkdir -p "${STRAPI_INSTALL_DIR}"

log_info "Scaffolding Strapi project at ${TARGET_DIR} (this may take a few minutes)..."
cd "${STRAPI_INSTALL_DIR}"

# Use --quickstart for SQLite (no extra DB setup needed)
if npx create-strapi@latest "${STRAPI_PROJECT_NAME}" --quickstart --no-run; then
log_ok "Strapi project '${STRAPI_PROJECT_NAME}' created at ${TARGET_DIR}."
Comment on lines +49 to +51
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

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

Using npx create-strapi@latest makes scaffolding non-deterministic across runs and can unexpectedly break CI when upstream releases change prompts/defaults. Consider parameterizing the version (e.g., STRAPI_CREATE_VERSION) and defaulting to a pinned version for repeatable installs.

Copilot uses AI. Check for mistakes.
log_info " To start Strapi: cd ${TARGET_DIR} && npm run develop"
log_info " Default port: 1337"
log_info " Admin panel: http://localhost:1337/admin"
log_info " Docs: https://docs.strapi.io/cms/installation/cli"
else
log_err "Failed to scaffold Strapi project."
return 1
fi
}

check_node && install_strapi
14 changes: 14 additions & 0 deletions ci/script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,17 @@ if [ ! -f "GeoIP.mmdb" ]; then
fi

chmod 755 1pctl install.sh

# Make application installer scripts executable
SCRIPT_DIR="$(dirname "$0")"
for installer in \
install_ai_tools.sh \
install_odoo.sh \
install_shopify.sh \
install_contentful.sh \
install_strapi.sh \
install_react_bricks.sh; do
Comment on lines +44 to +50
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

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

ci/script.sh is attempting to chmod install_ai_tools.sh, but that file does not exist anywhere in ci/ on this branch. This makes the installer list misleading; either add the missing script or remove it from the loop to keep the CI script self-consistent.

Copilot uses AI. Check for mistakes.
if [ -f "${SCRIPT_DIR}/${installer}" ]; then
chmod +x "${SCRIPT_DIR}/${installer}"
fi
done