Skip to content
Open
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
14 changes: 7 additions & 7 deletions apps/api/tests/RUNNING_TESTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@ docker compose -f docker-compose-test.yml down -v

## How it works

| Service | Image | Purpose |
| ------------ | -------------------------------------------------- | --------------------------------------------- |
| `test-db` | `postgres:15.7-alpine` | Application database |
| `test-redis` | `valkey/valkey:7.2.11-alpine` | Cache / Celery broker |
| `test-mq` | `rabbitmq:3.13.6-management-alpine` | Task queue |
| `test-minio` | `quay.io/minio/minio:RELEASE.2025-09-07T16-13-09Z` | S3-compatible object storage |
| `api-tests` | built from `apps/api/Dockerfile.dev` | Installs `requirements/test.txt`, runs pytest |
| Service | Image | Purpose |
| ------------ | ---------------------------------------------------- | --------------------------------------------- |
| `test-db` | `postgres:15.7-alpine` | Application database |
| `test-redis` | `valkey/valkey:7.2.11-alpine` | Cache / Celery broker |
| `test-mq` | `rabbitmq:3.13.6-management-alpine` | Task queue |
| `test-minio` | `docker.io/pgsty/minio:RELEASE.2026-08-04T00-00-00Z` | S3-compatible object storage |
| `api-tests` | built from `apps/api/Dockerfile.dev` | Installs `requirements/test.txt`, runs pytest |

All four dependencies expose health checks; `api-tests` waits for `service_healthy` on each via `depends_on`, so pytest only starts once the stack is ready.

Expand Down
2 changes: 1 addition & 1 deletion deployments/cli/community/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ services:

# Comment this if you using any external s3 compatible storage
plane-minio:
image: quay.io/minio/minio:RELEASE.2025-09-07T16-13-09Z
image: docker.io/pgsty/minio:RELEASE.2026-08-04T00-00-00Z
command: server /export --console-address ":9090"
deploy:
replicas: 1
Expand Down
136 changes: 91 additions & 45 deletions deployments/cli/community/restore-airgapped.sh
Original file line number Diff line number Diff line change
@@ -1,23 +1,49 @@
#!/bin/bash
+set -euo pipefail
set -euo pipefail

function print_header() {
clear

cat <<"EOF"
--------------------------------------------
____ _ /////////
| _ \| | __ _ _ __ ___ /////////
| |_) | |/ _` | '_ \ / _ \ ///// /////
| __/| | (_| | | | | __/ ///// /////
|_| |_|\__,_|_| |_|\___| ////
////
--------------------------------------------
Project management tool from the future
--------------------------------------------
##+. ##+ .##-
######+.######-.######.
#######. -### +#####+.
#######. + +######.
#######. .#######
#######. .#######
####### + .#######
.+#####+ ###- .#######
.######.-#####+.+######
-##. -## .+##
EOF
}

# Replace $2 (dest) with $1 (src), keeping the old dest recoverable until the
# swap succeeds. Rolls the old data back if the move fails.
function replaceDir() {
local src="$1" dest="$2" label="$3"
local old="${dest}.old.$$"

if [ -d "$dest" ]; then
mv "$dest" "$old"
Comment thread
coderabbitai[bot] marked this conversation as resolved.
# Restore the old data if we are interrupted mid-swap
trap "mv \"$old\" \"$dest\" 2>/dev/null || true; exit 1" INT TERM HUP
Comment thread
akshat5302 marked this conversation as resolved.
fi

if mv "$src" "$dest"; then
trap - INT TERM HUP
rm -rf "$old"
echo "Renamed $label"
else
trap - INT TERM HUP
echo "Error: Failed to install $label; restoring previous data"
if [ -d "$old" ]; then
mv "$old" "$dest"
fi
exit 1
fi
}

function restoreData() {

echo ""
Expand All @@ -27,7 +53,7 @@ function restoreData() {
echo ""

# set the backup folder path
BACKUP_FOLDER=${1}
BACKUP_FOLDER="${1:-}"

if [ -z "$BACKUP_FOLDER" ]; then
BACKUP_FOLDER="$PWD/backup"
Expand All @@ -46,6 +72,8 @@ function restoreData() {
# check if there are any .tar.gz files in the backup folder
if ! ls "$BACKUP_FOLDER"/*.tar.gz 1> /dev/null 2>&1; then
echo "Error: Backup folder does not contain .tar.gz files"
echo ""
echo "Usage: $0 /path/to/backup"
exit 1
fi

Expand Down Expand Up @@ -76,57 +104,75 @@ function restoreData() {
exit 1
fi

local dockerServiceStatus
local dockerServiceStatus compose_output
if command -v jq &> /dev/null; then
dockerServiceStatus=$($COMPOSE_CMD ls --filter name=plane-airgapped --format=json | jq -r .[0].Status)
if ! compose_output=$($COMPOSE_CMD ls --filter name=plane-airgapped --format=json); then
echo "Error: Failed to query Docker Compose services"
exit 1
fi
dockerServiceStatus=$(printf '%s\n' "$compose_output" | jq -r '.[0].Status // empty')
else
Comment thread
akshat5302 marked this conversation as resolved.
dockerServiceStatus=$($COMPOSE_CMD ls --filter name=plane-airgapped | grep -o "running" | head -n 1)
if ! compose_output=$($COMPOSE_CMD ls --filter name=plane-airgapped); then
echo "Error: Failed to query Docker Compose services"
exit 1
fi
dockerServiceStatus=$(printf '%s\n' "$compose_output" | grep -o "running" | head -n 1 || true)
fi

if [[ $dockerServiceStatus == "running" ]]; then
if [[ "$dockerServiceStatus" == running* ]]; then
echo "Plane Airgapped is running. Please STOP the Plane Airgapped before restoring data."
exit 1
fi

CURRENT_USER_ID=$(id -u)
CURRENT_GROUP_ID=$(id -g)

DATA_DIR="$AIRGAPPED_INSTALL_PATH/data"

# if the data folder not exists, create it
if [ ! -d "$AIRGAPPED_INSTALL_PATH/data" ]; then
mkdir -p "$AIRGAPPED_INSTALL_PATH/data"
chown -R $CURRENT_USER_ID:$CURRENT_GROUP_ID "$AIRGAPPED_INSTALL_PATH/data"
if [ ! -d "$DATA_DIR" ]; then
mkdir -p "$DATA_DIR"
chown -R $CURRENT_USER_ID:$CURRENT_GROUP_ID "$DATA_DIR"
fi

for BACKUP_FILE in "$BACKUP_FOLDER/*.tar.gz"; do
if [ -e "$BACKUP_FILE" ]; then

# get the basefilename without the extension
BASE_FILE_NAME=$(basename "$BACKUP_FILE" ".tar.gz")

# extract the restoreFile to the airgapped instance install path
echo "Restoring $BASE_FILE_NAME"
rm -rf "$AIRGAPPED_INSTALL_PATH/data/$BASE_FILE_NAME" || true

tar -xvzf "$BACKUP_FILE" -C "$AIRGAPPED_INSTALL_PATH/data/"
if [ $? -ne 0 ]; then
echo "Error: Failed to extract $BACKUP_FILE"
exit 1
fi
chown -R $CURRENT_USER_ID:$CURRENT_GROUP_ID "$AIRGAPPED_INSTALL_PATH/data/$BASE_FILE_NAME"
if [ $? -ne 0 ]; then
echo "Error: Failed to change ownership of $AIRGAPPED_INSTALL_PATH/data/$BASE_FILE_NAME"
exit 1
fi
else
echo "No .tar.gz files found in the current directory."
echo ""
echo "Please provide the path to the backup file."
echo ""
echo "Usage: $0 /path/to/backup"
# Remove stale extracted source directories from a previous run so tar
# does not merge new files into old data
rm -rf "$DATA_DIR/pgdata" "$DATA_DIR/redisdata" "$DATA_DIR/uploads" "$DATA_DIR/rabbitmq_data"

# Extract all backup tar files
for BACKUP_FILE in "$BACKUP_FOLDER"/*.tar.gz; do
Comment thread
akshat5302 marked this conversation as resolved.
BASE_FILE_NAME=$(basename "$BACKUP_FILE" ".tar.gz")
echo "Extracting $BASE_FILE_NAME"
if ! tar -xzvf "$BACKUP_FILE" -C "$DATA_DIR/"; then
echo "Error: Failed to extract $BACKUP_FILE"
exit 1
fi
done

# Rename extracted directories to match docker-compose volume paths
# Backup tars: pgdata, redisdata, uploads, rabbitmq_data
# Docker-compose expects: db, redis, minio/uploads, mq

if [ -d "$DATA_DIR/pgdata" ]; then
replaceDir "$DATA_DIR/pgdata" "$DATA_DIR/db" "pgdata -> db"
fi

if [ -d "$DATA_DIR/redisdata" ]; then
replaceDir "$DATA_DIR/redisdata" "$DATA_DIR/redis" "redisdata -> redis"
fi

if [ -d "$DATA_DIR/uploads" ]; then
mkdir -p "$DATA_DIR/minio"
replaceDir "$DATA_DIR/uploads" "$DATA_DIR/minio/uploads" "uploads -> minio/uploads"
fi

if [ -d "$DATA_DIR/rabbitmq_data" ]; then
replaceDir "$DATA_DIR/rabbitmq_data" "$DATA_DIR/mq" "rabbitmq_data -> mq"
fi

# Fix ownership on all restored data
chown -R $CURRENT_USER_ID:$CURRENT_GROUP_ID "$DATA_DIR"

echo ""
echo "Restore completed successfully."
echo ""
Expand Down
2 changes: 1 addition & 1 deletion docker-compose-local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ services:
RABBITMQ_DEFAULT_VHOST: ${RABBITMQ_VHOST}

plane-minio:
image: quay.io/minio/minio:RELEASE.2025-09-07T16-13-09Z
image: docker.io/pgsty/minio:RELEASE.2026-08-04T00-00-00Z
Comment thread
akshat5302 marked this conversation as resolved.
restart: unless-stopped
networks:
- dev_env
Expand Down
2 changes: 1 addition & 1 deletion docker-compose-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ services:
retries: 10

test-minio:
image: quay.io/minio/minio:RELEASE.2025-09-07T16-13-09Z
image: docker.io/pgsty/minio:RELEASE.2026-08-04T00-00-00Z
networks:
- test_env
env_file:
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ services:

plane-minio:
container_name: plane-minio
image: quay.io/minio/minio:RELEASE.2025-09-07T16-13-09Z
image: docker.io/pgsty/minio:RELEASE.2026-08-04T00-00-00Z
restart: always
command: server /export --console-address ":9090"
volumes:
Expand Down
Loading