Skip to content

fix: expand the source id regex item part #666

fix: expand the source id regex item part

fix: expand the source id regex item part #666

# SPDX-FileCopyrightText: Nextcloud contributors
# SPDX-License-Identifier: AGPL-3.0-or-later
name: Integration test
on:
pull_request:
push:
branches:
- main
- stable*
env:
APP_NAME: context_chat
permissions:
contents: read
concurrency:
group: integration-test-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
scan-test:
runs-on: ubuntu-22.04
strategy:
# do not stop on another job's failure
fail-fast: false
matrix:
php-versions: [ '8.1' ]
databases: [ 'pgsql' ]
server-versions: [ 'stable32', 'master' ]
encryption: ['on', 'off']
exclude:
- server-versions: stable32
databases: pgsql
php-versions: 8.1
encryption: on
name: Integration test ☁️${{ matrix.server-versions }} 🐘${{ matrix.php-versions }} 🔐:${{ matrix.encryption }}
env:
MYSQL_PORT: 4444
PGSQL_PORT: 4445
# use the same db for ccb and nextcloud
CCB_DB_URL: postgresql+psycopg://root:rootpassword@localhost:4445/nextcloud
services:
mysql:
image: mariadb:10.5
ports:
- 4444:3306/tcp
env:
MYSQL_ROOT_PASSWORD: rootpassword
options: --health-cmd="mysqladmin ping" --health-interval 5s --health-timeout 2s --health-retries 5
postgres:
image: pgvector/pgvector:pg17
ports:
- 4445:5432/tcp
env:
POSTGRES_USER: root
POSTGRES_PASSWORD: rootpassword
POSTGRES_DB: nextcloud
options: --health-cmd pg_isready --health-interval 5s --health-timeout 2s --health-retries 5
steps:
- name: Checkout server
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
repository: nextcloud/server
ref: ${{ matrix.server-versions }}
submodules: recursive
persist-credentials: false
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@cf4cade2721270509d5b1c766ab3549210a39a2a # 2.33.0
with:
php-version: ${{ matrix.php-versions }}
tools: phpunit
extensions: mbstring, iconv, fileinfo, intl, sqlite, pdo_mysql, pdo_sqlite, pgsql, pdo_pgsql, gd, zip
- name: Checkout app
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: apps/${{ env.APP_NAME }}
persist-credentials: false
- name: Checkout backend
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
repository: nextcloud/context_chat_backend
path: context_chat_backend/
persist-credentials: false
- name: Get backend app version
id: appinfo
uses: skjnldsv/xpath-action@7e6a7c379d0e9abc8acaef43df403ab4fc4f770c # master
with:
filename: context_chat_backend/appinfo/info.xml
expression: "/info/version/text()"
- name: Read package.json node and npm engines version
uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3
id: versions
with:
path: apps/${{ env.APP_NAME }}
fallbackNode: '^20'
fallbackNpm: '^10'
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: ${{ steps.versions.outputs.nodeVersion }}
- name: Set up npm ${{ steps.versions.outputs.npmVersion }}
run: npm i -g npm@"${{ steps.versions.outputs.npmVersion }}"
- name: Install app
working-directory: apps/${{ env.APP_NAME }}
run: |
make all
composer install --no-dev
- name: Set up Nextcloud
if: ${{ matrix.databases != 'pgsql'}}
run: |
sleep 25
mkdir data
./occ maintenance:install --verbose --database=${{ matrix.databases }} --database-name=nextcloud --database-host=127.0.0.1 --database-port=$MYSQL_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password
composer run serve &
- name: Set up Nextcloud
if: ${{ matrix.databases == 'pgsql'}}
run: |
sleep 25
mkdir data
./occ maintenance:install --verbose --database=${{ matrix.databases }} --database-name=nextcloud --database-host=127.0.0.1 --database-port=$PGSQL_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password
composer run serve &
- name: Enable context_chat, app_api and testing
run: ./occ app:enable -vvv -f ${{ env.APP_NAME }} app_api testing
- name: Enable encryption
if: ${{ matrix.encryption == 'on' }}
run: |
./occ app:enable -vvv -f encryption
./occ encryption:enable
- name: Checkout documentation
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
repository: nextcloud/documentation
path: data/admin/files/documentation
persist-credentials: false
- name: Checkout pdfs
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
repository: papers-we-love/papers-we-love
path: data/admin/files/papers
persist-credentials: false
- name: Prepare docs
run: |
cd data/admin/files
mv documentation/admin_manual .
cp -R documentation/developer_manual .
cd developer_manual
find . -type f -name "*.rst" -exec bash -c 'mv "$0" "${0%.rst}.md"' {} \;
cd ..
cp -R documentation/developer_manual ./developer_manual2
cd developer_manual2
find . -type f -name "*.rst" -exec bash -c 'mv "$0" "${0%.rst}.txt"' {} \;
cd ..
rm -rf documentation
- name: Reduce number of files
run: |
cd data/admin/files
LIMIT=100
# Find all files in the directory and its subdirectories
FILES=($(find papers/ -type f))
# Count the number of files
FILE_COUNT=${#FILES[@]}
# Check if the current number of files exceeds the limit
if [ "$FILE_COUNT" -le "$LIMIT" ]; then
echo "No files need to be deleted. Current count: $FILE_COUNT"
exit 0
fi
# Calculate how many files to delete
FILES_TO_DELETE=$((FILE_COUNT - LIMIT))
# Sort files by modification time (oldest first) and delete the oldest ones
for FILE in $(ls -t "${FILES[@]}" | tail -n "$FILES_TO_DELETE"); do
echo "Deleting: $FILE"
rm "$FILE"
done
echo "Deleted $FILES_TO_DELETE files. Current count: $((FILE_COUNT - FILES_TO_DELETE))"
- name: Setup python 3.11
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.11'
cache: 'pip'
cache-dependency-path: context_chat_backend/requirements.txt
- name: Install and init backend
run: |
cd context_chat_backend
pip install --upgrade pip setuptools wheel
pip install -r requirements.txt
cp example.env .env
echo "NEXTCLOUD_URL=http://localhost:8080" >> .env
python3 -u ./main_em.py > em_backend_logs 2>&1 &
python3 -u ./main.py > backend_logs 2>&1 &
echo $! > ../pid.txt # Save the process ID (PID)
sleep 60 # Wait for the backend to get ready
- name: Register backend
run: |
set -x
./occ config:system:set debug --value true
./occ config:system:set loglevel --value 0
./occ app_api:daemon:register --net host manual_install "Manual Install" manual-install http localhost http://localhost:8080
timeout 120 ./occ app_api:app:register context_chat_backend manual_install --json-info "{\"appid\":\"context_chat_backend\",\"name\":\"Context Chat Backend\",\"daemon_config_name\":\"manual_install\",\"version\":\"${{ fromJson(steps.appinfo.outputs.result).version }}\",\"secret\":\"12345\",\"port\":10034,\"scopes\":[],\"system_app\":0}" --force-scopes --wait-finish
- name: Scan files, baseline
run: |
./occ files:scan admin
./occ context_chat:scan admin -m text/plain
- name: Check python memory usage
run: |
ps -p $(cat pid.txt) -o pid,cmd,%mem,rss --sort=-%mem
ps -p $(cat pid.txt) -o %mem --no-headers > initial_mem.txt
- name: Scan files
run: |
./occ files:scan admin
./occ context_chat:scan admin -m text/markdown &
./occ context_chat:scan admin -m text/x-rst &
./occ context_chat:scan admin -m application/pdf &
wait
- name: Check stats
run: |
./occ context_chat:stats
- name: Check python memory usage
run: |
ps -p $(cat pid.txt) -o pid,cmd,%mem,rss --sort=-%mem
ps -p $(cat pid.txt) -o %mem --no-headers > after_scan_mem.txt
- name: Run the prompts
run: |
./occ background-job:worker -v 'OC\TaskProcessing\SynchronousBackgroundJob' &
WORKER1_PID=$!
./occ background-job:worker -v 'OC\TaskProcessing\SynchronousBackgroundJob' &
WORKER2_PID=$!
OUT1=$(./occ context_chat:prompt admin "Which factors are taken into account for the Ethical AI Rating?")
echo "$OUT1"
echo '--------------------------------------------------'
OUT2=$(./occ context_chat:prompt admin "Welche Faktoren beeinflussen das Ethical AI Rating?")
echo "$OUT2"
echo '--------------------------------------------------'
OUT3=$(./occ context_chat:search admin "Welche Faktoren beeinflussen das Ethical AI Rating?")
echo "$OUT3"
echo "$OUT1" | grep -q "If all of these points are met, we give a Green label." || exit 1
echo "$OUT2" | grep -q "If all of these points are met, we give a Green label." || exit 1
echo "$OUT3" | grep -q "overview.rst" || exit 1
kill -9 $WORKER1_PID
kill -9 $WORKER2_PID
- name: Check python memory usage
run: |
ps -p $(cat pid.txt) -o pid,cmd,%mem,rss --sort=-%mem
ps -p $(cat pid.txt) -o %mem --no-headers > after_prompt_mem.txt
- name: Compare memory usage and detect leak
run: |
initial_mem=$(cat initial_mem.txt | tr -d ' ')
final_mem=$(cat after_scan_mem.txt | tr -d ' ')
echo "Initial Memory Usage: $initial_mem%"
echo "Memory Usage after scan: $final_mem%"
if (( $(echo "$final_mem > $initial_mem" | bc -l) )); then
echo "Memory usage has increased during scan. Possible memory leak detected!"
else
echo "Memory usage during scan is stable. No memory leak detected."
fi
- name: Compare memory usage and detect leak
run: |
initial_mem=$(cat after_scan_mem.txt | tr -d ' ')
final_mem=$(cat after_prompt_mem.txt | tr -d ' ')
echo "Initial Memory Usage: $initial_mem%"
echo "Memory Usage after prompt: $final_mem%"
if (( $(echo "$final_mem > $initial_mem" | bc -l) )); then
echo "Memory usage has increased during prompt. Possible memory leak detected!"
else
echo "Memory usage during prompt is stable. No memory leak detected."
fi
- name: Show nextcloud logs
if: always()
run: |
cat data/nextcloud.log
- name: Show context chat logs
if: always()
run: |
cat data/context_chat.log
- name: Show backend logs
if: always()
run: |
cat context_chat_backend/backend_logs || echo "No main backend logs"
cat context_chat_backend/em_backend_logs || echo "No embedding server logs"
echo '--------------------------------------------------'
tail -v -n +1 context_chat_backend/persistent_storage/logs/* || echo "No logs in logs directory"
cron-test:
runs-on: ubuntu-22.04
strategy:
# do not stop on another job's failure
fail-fast: false
matrix:
php-versions: [ '8.1' ]
databases: [ 'pgsql' ]
server-versions: [ 'stable32', 'master' ]
encryption: ['on', 'off']
exclude:
- server-versions: stable32
databases: pgsql
php-versions: 8.1
encryption: on
name: Integration test with cron ☁️${{ matrix.server-versions }} 🐘${{ matrix.php-versions }} 🔐:${{ matrix.encryption }}
env:
MYSQL_PORT: 4444
PGSQL_PORT: 4445
# use the same db for ccb and nextcloud
CCB_DB_URL: postgresql+psycopg://root:rootpassword@localhost:4445/nextcloud
services:
mysql:
image: mariadb:10.5
ports:
- 4444:3306/tcp
env:
MYSQL_ROOT_PASSWORD: rootpassword
options: --health-cmd="mysqladmin ping" --health-interval 5s --health-timeout 2s --health-retries 5
postgres:
image: pgvector/pgvector:pg17
ports:
- 4445:5432/tcp
env:
POSTGRES_USER: root
POSTGRES_PASSWORD: rootpassword
POSTGRES_DB: nextcloud
options: --health-cmd pg_isready --health-interval 5s --health-timeout 2s --health-retries 5
steps:
- name: Checkout server
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
repository: nextcloud/server
ref: ${{ matrix.server-versions }}
submodules: recursive
persist-credentials: false
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@cf4cade2721270509d5b1c766ab3549210a39a2a # 2.33.0
with:
php-version: ${{ matrix.php-versions }}
tools: phpunit
extensions: mbstring, iconv, fileinfo, intl, sqlite, pdo_mysql, pdo_sqlite, pgsql, pdo_pgsql, gd, zip
- name: Checkout app
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: apps/${{ env.APP_NAME }}
persist-credentials: false
- name: Checkout backend
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
repository: nextcloud/context_chat_backend
path: context_chat_backend/
persist-credentials: false
- name: Get backend app version
id: appinfo
uses: skjnldsv/xpath-action@7e6a7c379d0e9abc8acaef43df403ab4fc4f770c # master
with:
filename: context_chat_backend/appinfo/info.xml
expression: "/info/version/text()"
- name: Read package.json node and npm engines version
uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3
id: versions
with:
path: apps/${{ env.APP_NAME }}
fallbackNode: '^20'
fallbackNpm: '^10'
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: ${{ steps.versions.outputs.nodeVersion }}
- name: Set up npm ${{ steps.versions.outputs.npmVersion }}
run: npm i -g npm@"${{ steps.versions.outputs.npmVersion }}"
- name: Install app
working-directory: apps/${{ env.APP_NAME }}
run: |
make all
composer install --no-dev
- name: Set up Nextcloud
if: ${{ matrix.databases != 'pgsql'}}
run: |
sleep 25
mkdir data
./occ maintenance:install --verbose --database=${{ matrix.databases }} --database-name=nextcloud --database-host=127.0.0.1 --database-port=$MYSQL_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password
composer run serve &
- name: Set up Nextcloud
if: ${{ matrix.databases == 'pgsql'}}
run: |
sleep 25
mkdir data
./occ maintenance:install --verbose --database=${{ matrix.databases }} --database-name=nextcloud --database-host=127.0.0.1 --database-port=$PGSQL_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password
composer run serve &
- name: Enable app_api and testing
run: ./occ app:enable -vvv -f app_api testing
- name: Enable encryption
if: ${{ matrix.encryption == 'on' }}
run: |
./occ app:enable -vvv -f encryption
./occ encryption:enable
- name: Setup python 3.11
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.11'
cache: 'pip'
cache-dependency-path: context_chat_backend/requirements.txt
- name: Install and init backend
run: |
cd context_chat_backend
pip install --upgrade pip setuptools wheel
pip install -r requirements.txt
cp example.env .env
echo "NEXTCLOUD_URL=http://localhost:8080" >> .env
python3 -u ./main_em.py > em_backend_logs 2>&1 &
python3 -u ./main.py > backend_logs 2>&1 &
echo $! > ../pid.txt # Save the process ID (PID)
sleep 60 # Wait for the backend to get ready
- name: Register backend
run: |
set -x
./occ config:system:set debug --value true
./occ config:system:set loglevel --value 0
./occ app_api:daemon:register --net host manual_install "Manual Install" manual-install http localhost http://localhost:8080
timeout 120 ./occ app_api:app:register context_chat_backend manual_install --json-info "{\"appid\":\"context_chat_backend\",\"name\":\"Context Chat Backend\",\"daemon_config_name\":\"manual_install\",\"version\":\"${{ fromJson(steps.appinfo.outputs.result).version }}\",\"secret\":\"12345\",\"port\":10034,\"scopes\":[],\"system_app\":0}" --force-scopes --wait-finish
- name: Checkout documentation
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
repository: nextcloud/documentation
path: data/admin/files/documentation
persist-credentials: false
- name: Checkout pdfs
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
repository: papers-we-love/papers-we-love
path: data/admin/files/papers
ref: ad039b1e29ddb6ab1e217d39f16a5051c18ccc5a # to be deterministic
persist-credentials: false
- name: Prepare docs
run: |
cd data/admin/files
mv documentation/admin_manual .
cp -R documentation/developer_manual .
cd developer_manual
find . -type f -name "*.rst" -exec bash -c 'mv "$0" "${0%.rst}.md"' {} \;
cd ..
cp -R documentation/developer_manual ./developer_manual2
cd developer_manual2
find . -type f -name "*.rst" -exec bash -c 'mv "$0" "${0%.rst}.txt"' {} \;
cd ..
rm -rf documentation
- name: Reduce number of files
run: |
cd data/admin/files
LIMIT=100
# Find all files in the directory and its subdirectories
FILES=($(find papers/ -type f))
# Count the number of files
FILE_COUNT=${#FILES[@]}
# Check if the current number of files exceeds the limit
if [ "$FILE_COUNT" -le "$LIMIT" ]; then
echo "No files need to be deleted. Current count: $FILE_COUNT"
exit 0
fi
# Calculate how many files to delete
FILES_TO_DELETE=$((FILE_COUNT - LIMIT))
# Sort files by modification time (oldest first) and delete the oldest ones
for FILE in $(ls -t "${FILES[@]}" | tail -n "$FILES_TO_DELETE"); do
echo "Deleting: $FILE"
rm "$FILE"
done
echo "Deleted $FILES_TO_DELETE files. Current count: $((FILE_COUNT - FILES_TO_DELETE))"
- name: Run files scan
run: |
./occ files:scan admin # Do the scan before enabling context chat
- name: Enable context chat
run: ./occ app:enable -vvv -f ${{ env.APP_NAME }}
- name: Run indexer cron
run: |
# Run cron in speed mode: Set interval to 0 minutes
./occ config:app:set --value 30 --type integer context_chat indexing_job_interval # 30 seconds
./occ config:app:set --value 10 --type integer context_chat crawl_job_interval # 10 seconds
./occ config:app:set --value 10 --type integer context_chat action_job_interval # 10 seconds
./occ config:app:set --value 10 --type integer context_chat fs_listener_job_interval # 10 seconds
for i in {1..100}; do
php cron.php & # Starting with stable31 we can use -v here for better visibility
wait
./occ context_chat:stats
done
- name: Check context chat state
run: |
./occ context_chat:stats
./occ background-job:list
./occ context_chat:stats | grep -q "Index complete time" || echo "Indexing did not complete"
./occ context_chat:stats | awk '
/Total eligible files/ {
total = $NF + 0 # force conversion to number
}
/files__default/ {
indexed = $NF;
sub(/,$/, "", indexed) # remove trailing comma
indexed = indexed + 0 # force conversion to number
}
END {
low = total * 0.85;
high = total * 1.15;
if (indexed >= low && indexed <= high) {
print "✅ Indexed files (" indexed ") are within 15% of eligible files (" total ").";
exit 0;
} else {
print "❌ Indexed files (" indexed ") are OUTSIDE the 15% range of eligible files (" total ").";
exit 1;
}
}
'
- name: Run the prompts
run: |
./occ background-job:worker -v 'OC\TaskProcessing\SynchronousBackgroundJob' &
WORKER1_PID=$!
./occ background-job:worker -v 'OC\TaskProcessing\SynchronousBackgroundJob' &
WORKER2_PID=$!
OUT1=$(./occ context_chat:prompt admin "Which factors are taken into account for the Ethical AI Rating?")
echo "$OUT1"
echo '--------------------------------------------------'
OUT2=$(./occ context_chat:prompt admin "Welche Faktoren beeinflussen das Ethical AI Rating?")
echo "$OUT2"
echo '--------------------------------------------------'
OUT3=$(./occ context_chat:search admin "Welche Faktoren beeinflussen das Ethical AI Rating?")
echo "$OUT3"
echo "$OUT1" | grep -q "If all of these points are met, we give a Green label." || exit 1
echo "$OUT2" | grep -q "If all of these points are met, we give a Green label." || exit 1
echo "$OUT3" | grep -q "overview.rst" || exit 1
kill -9 $WORKER1_PID
kill -9 $WORKER2_PID
- name: Show nextcloud logs
if: always()
run: |
cat data/nextcloud.log
- name: Show context chat logs
if: always()
run: |
cat data/context_chat.log
- name: Show backend logs
if: always()
run: |
cat context_chat_backend/backend_logs || echo "No main backend logs"
cat context_chat_backend/em_backend_logs || echo "No embedding server logs"
echo '--------------------------------------------------'
tail -v -n +1 context_chat_backend/persistent_storage/logs/* || echo "No logs in logs directory"
listener-test:
runs-on: ubuntu-22.04
strategy:
# do not stop on another job's failure
fail-fast: false
matrix:
php-versions: [ '8.1' ]
databases: [ 'pgsql' ]
server-versions: [ 'stable32', 'master' ]
encryption: ['on', 'off']
file-deletion-method: [ 'occ', 'os' ]
exclude:
- server-versions: stable32
file-deletion-method: os
databases: pgsql
php-versions: 8.1
encryption: on
- server-versions: stable32
file-deletion-method: os
databases: pgsql
php-versions: 8.1
encryption: off
name: Integration test with file listener ☁️${{ matrix.server-versions }} 🐘${{ matrix.php-versions }} 🗑️${{ matrix.file-deletion-method }} 🔐:${{ matrix.encryption }}
env:
MYSQL_PORT: 4444
PGSQL_PORT: 4445
# use the same db for ccb and nextcloud
CCB_DB_URL: postgresql+psycopg://root:rootpassword@localhost:4445/nextcloud
services:
mysql:
image: mariadb:10.5
ports:
- 4444:3306/tcp
env:
MYSQL_ROOT_PASSWORD: rootpassword
options: --health-cmd="mysqladmin ping" --health-interval 5s --health-timeout 2s --health-retries 5
postgres:
image: pgvector/pgvector:pg17
ports:
- 4445:5432/tcp
env:
POSTGRES_USER: root
POSTGRES_PASSWORD: rootpassword
POSTGRES_DB: nextcloud
options: --health-cmd pg_isready --health-interval 5s --health-timeout 2s --health-retries 5
steps:
- name: Checkout server
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
repository: nextcloud/server
ref: ${{ matrix.server-versions }}
submodules: recursive
persist-credentials: false
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@cf4cade2721270509d5b1c766ab3549210a39a2a # 2.33.0
with:
php-version: ${{ matrix.php-versions }}
tools: phpunit
extensions: mbstring, iconv, fileinfo, intl, sqlite, pdo_mysql, pdo_sqlite, pgsql, pdo_pgsql, gd, zip
- name: Checkout app
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: apps/${{ env.APP_NAME }}
persist-credentials: false
- name: Checkout backend
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
repository: nextcloud/context_chat_backend
path: context_chat_backend/
persist-credentials: false
- name: Get backend app version
id: appinfo
uses: skjnldsv/xpath-action@7e6a7c379d0e9abc8acaef43df403ab4fc4f770c # master
with:
filename: context_chat_backend/appinfo/info.xml
expression: "/info/version/text()"
- name: Read package.json node and npm engines version
uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3
id: versions
with:
path: apps/${{ env.APP_NAME }}
fallbackNode: '^20'
fallbackNpm: '^10'
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: ${{ steps.versions.outputs.nodeVersion }}
- name: Set up npm ${{ steps.versions.outputs.npmVersion }}
run: npm i -g npm@"${{ steps.versions.outputs.npmVersion }}"
- name: Install app
working-directory: apps/${{ env.APP_NAME }}
run: |
make all
composer install --no-dev
- name: Set up Nextcloud
if: ${{ matrix.databases != 'pgsql'}}
run: |
sleep 25
mkdir data
./occ maintenance:install --verbose --database=${{ matrix.databases }} --database-name=nextcloud --database-host=127.0.0.1 --database-port=$MYSQL_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password
composer run serve &
- name: Set up Nextcloud
if: ${{ matrix.databases == 'pgsql'}}
run: |
sleep 25
mkdir data
./occ maintenance:install --verbose --database=${{ matrix.databases }} --database-name=nextcloud --database-host=127.0.0.1 --database-port=$PGSQL_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password
composer run serve &
- name: Enable app_api and testing
run: ./occ app:enable -vvv -f app_api testing
- name: Enable encryption
if: ${{ matrix.encryption == 'on' }}
run: |
./occ app:enable -vvv -f encryption
./occ encryption:enable
- name: Setup python 3.11
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.11'
cache: 'pip'
cache-dependency-path: context_chat_backend/requirements.txt
- name: Install and init backend
run: |
cd context_chat_backend
pip install --upgrade pip setuptools wheel
pip install -r requirements.txt
cp example.env .env
echo "NEXTCLOUD_URL=http://localhost:8080" >> .env
python3 -u ./main_em.py > em_backend_logs 2>&1 &
python3 -u ./main.py > backend_logs 2>&1 &
echo $! > ../pid.txt # Save the process ID (PID)
sleep 60 # Wait for the backend to get ready
- name: Register backend
run: |
set -x
./occ config:system:set debug --value true
./occ config:system:set loglevel --value 0
./occ app_api:daemon:register --net host manual_install "Manual Install" manual-install http localhost http://localhost:8080
timeout 120 ./occ app_api:app:register context_chat_backend manual_install --json-info "{\"appid\":\"context_chat_backend\",\"name\":\"Context Chat Backend\",\"daemon_config_name\":\"manual_install\",\"version\":\"${{ fromJson(steps.appinfo.outputs.result).version }}\",\"secret\":\"12345\",\"port\":10034,\"scopes\":[],\"system_app\":0}" --force-scopes --wait-finish
- name: Enable context chat
run: |
./occ app:enable -vvv -f ${{ env.APP_NAME }}
# Run cron in speed mode
./occ config:app:set --value 30 --type integer context_chat indexing_job_interval # 30 seconds
./occ config:app:set --value 10 --type integer context_chat crawl_job_interval # 10 seconds
./occ config:app:set --value 10 --type integer context_chat action_job_interval # 10 seconds
./occ config:app:set --value 10 --type integer context_chat fs_listener_job_interval # 10 seconds
# Run normal indexing jobs which will only pick up welcome.txt etc
for i in {1..10}; do
php cron.php & # Starting with stable31 we can use -v here for better visibility
wait
./occ context_chat:stats
done
- name: Checkout documentation
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
repository: nextcloud/documentation
path: data/admin/files/documentation
persist-credentials: false
- name: Checkout pdfs
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
repository: papers-we-love/papers-we-love
path: data/admin/files/papers
ref: ad039b1e29ddb6ab1e217d39f16a5051c18ccc5a # to be deterministic
persist-credentials: false
- name: Prepare docs
run: |
cd data/admin/files
mv documentation/admin_manual .
cp -R documentation/developer_manual .
cd developer_manual
find . -type f -name "*.rst" -exec bash -c 'mv "$0" "${0%.rst}.md"' {} \;
cd ..
cp -R documentation/developer_manual ./developer_manual2
cd developer_manual2
find . -type f -name "*.rst" -exec bash -c 'mv "$0" "${0%.rst}.txt"' {} \;
cd ..
rm -rf documentation
- name: Reduce number of files
run: |
cd data/admin/files
LIMIT=100
# Find all files in the directory and its subdirectories
FILES=($(find papers/ -type f))
# Count the number of files
FILE_COUNT=${#FILES[@]}
# Check if the current number of files exceeds the limit
if [ "$FILE_COUNT" -le "$LIMIT" ]; then
echo "No files need to be deleted. Current count: $FILE_COUNT"
exit 0
fi
# Calculate how many files to delete
FILES_TO_DELETE=$((FILE_COUNT - LIMIT))
# Sort files by modification time (oldest first) and delete the oldest ones
for FILE in $(ls -t "${FILES[@]}" | tail -n "$FILES_TO_DELETE"); do
echo "Deleting: $FILE"
rm "$FILE"
done
echo "Deleted $FILES_TO_DELETE files. Current count: $((FILE_COUNT - FILES_TO_DELETE))"
- name: Run files scan
run: |
./occ files:scan admin # We do the scan after enabling context chat here, so we can test the file listeners
- name: Run indexer cron
run: |
for i in {1..100}; do
php cron.php & # Starting with stable31 we can use -v here for better visibility
wait
./occ context_chat:stats
done
- name: Check context chat state
run: |
./occ context_chat:stats
./occ background-job:list
./occ context_chat:stats | grep -q "Index complete time" || echo "Indexing did not complete"
./occ context_chat:stats | awk '
/Total eligible files/ {
total = $NF + 0 # force conversion to number
}
/files__default/ {
indexed = $NF;
sub(/,$/, "", indexed) # remove trailing comma
indexed = indexed + 0 # force conversion to number
}
END {
low = total * 0.85;
high = total * 1.15;
if (indexed >= low && indexed <= high) {
print "✅ Indexed files (" indexed ") are within 15% of eligible files (" total ").";
exit 0;
} else {
print "❌ Indexed files (" indexed ") are OUTSIDE the 15% range of eligible files (" total ").";
exit 1;
}
}
'
- name: Run the prompts
run: |
./occ background-job:worker -v 'OC\TaskProcessing\SynchronousBackgroundJob' &
WORKER1_PID=$!
./occ background-job:worker -v 'OC\TaskProcessing\SynchronousBackgroundJob' &
WORKER2_PID=$!
set +e
# Check for user admin: Should be there
OUT_ADMIN_ENGLISH_PROMPT_AI=$(./occ context_chat:prompt admin "Which factors are taken into account for the Ethical AI Rating?")
OUT_ADMIN_GERMAN_PROMPT_AI=$(./occ context_chat:prompt admin "Welche Faktoren beeinflussen das Ethical AI Rating?")
OUT_ADMIN_SEARCH_AI=$(./occ context_chat:search admin "Welche Faktoren beeinflussen das Ethical AI Rating?")
# Check for user test: Shouldn't be there
OUT_TEST_ENGLISH_PROMPT_AI=$(./occ context_chat:prompt test "Which factors are taken into account for the Ethical AI Rating?")
OUT_TEST_GERMAN_PROMPT_AI=$(./occ context_chat:prompt test "Welche Faktoren beeinflussen das Ethical AI Rating?")
OUT_TEST_SEARCH_AI=$(./occ context_chat:search test "Welche Faktoren beeinflussen das Ethical AI Rating?")
# Check for user test: Shouldn't be there, because it was not shared yet
OUT_TEST_PROMPT_JOBS=$(./occ context_chat:prompt test "How do I set my TimedJob to be time insensitive?")
OUT_TEST_SEARCH_JOBS=$(./occ context_chat:search test "How do I set my TimedJob to be time insensitive?")
echo "OUT_ADMIN_ENGLISH_PROMPT_AI"
echo "$OUT_ADMIN_ENGLISH_PROMPT_AI"
echo "OUT_ADMIN_GERMAN_PROMPT_AI"
echo "$OUT_ADMIN_GERMAN_PROMPT_AI"
echo "OUT_ADMIN_SEARCH_AI"
echo "$OUT_ADMIN_SEARCH_AI"
echo "OUT_TEST_ENGLISH_PROMPT_AI"
echo "$OUT_TEST_ENGLISH_PROMPT_AI"
echo "OUT_TEST_GERMAN_PROMPT_AI"
echo "$OUT_TEST_GERMAN_PROMPT_AI"
echo "OUT_TEST_SEARCH_AI"
echo "$OUT_TEST_SEARCH_AI"
echo "OUT_TEST_PROMPT_JOBS"
echo "$OUT_TEST_PROMPT_JOBS"
echo "OUT_TEST_SEARCH_JOBS"
echo "$OUT_TEST_SEARCH_JOBS"
echo "$OUT_ADMIN_ENGLISH_PROMPT_AI" | grep -q "If all of these points are met, we give a Green label." && echo '✅ Admin does see AI overview' || exit 1
echo "$OUT_ADMIN_GERMAN_PROMPT_AI" | grep -q "If all of these points are met, we give a Green label." && echo '✅ Admin does see AI overview, after german question' || exit 1
echo "$OUT_ADMIN_SEARCH_AI" | grep -q "overview.rst" && echo '✅ Admin does see AI overview, when using search' || exit 1
echo "$OUT_TEST_ENGLISH_PROMPT_AI" | grep -q -v "If all of these points are met, we give a Green label." && echo '✅ Test user does not see AI overview' || exit 1
echo "$OUT_TEST_GERMAN_PROMPT_AI" | grep -q -v "If all of these points are met, we give a Green label." && echo '✅Test user does not see AI overview, after german question' || exit 1
echo "$OUT_TEST_SEARCH_AI" | grep -q -v "overview.rst" && echo '✅Test user does not see AI overview, when using search' || exit 1
echo "$OUT_TEST_PROMPT_JOBS" | grep -q -v "background jobs" && echo '✅Test user does not see BackgroundJobs docs' || exit 1
echo "$OUT_TEST_SEARCH_JOBS" | grep -q -v "backgroundjobs.md" && echo '✅Test user does not see BackgroundJobs docs' || exit 1
kill -9 $WORKER1_PID
kill -9 $WORKER2_PID
- name: Remove some files using occ
if: ${{ matrix.file-deletion-method == 'occ'}}
run: |
./occ files:delete admin/files/admin_manual
- name: Remove some files using os
if: ${{ matrix.file-deletion-method == 'os'}}
run: |
cd data/admin/files
rm -rf ./admin_manual # this + files:scan sadly doesn't work, currently see https://github.com/nextcloud/context_chat/issues/153
cd ../../..
./occ files:scan admin # We run the scan again to check if the files are successfully removed from the vectordb
- name: Share some files
run: |
OC_PASS=test ./occ user:add --password-from-env -- test
# share developer_manual to test user
curl -X POST -u 'admin:password' -H 'OCS-APIRequest: true' 'http://localhost:8080/ocs/v2.php/apps/files_sharing/api/v1/shares?shareType=0&shareWith=test&path=developer_manual'
# list files to trigger mounting of shares
curl -X PROPFIND -H "Depth: 0" -u 'test:test' 'http://localhost:8080/remote.php/webdav/'
- name: Run indexer cron
run: |
for i in {1..100}; do
php cron.php & # Starting with stable31 we can use -v here for better visibility
wait
./occ context_chat:stats
done
- name: Run the prompts again
run: |
./occ background-job:worker -v 'OC\TaskProcessing\SynchronousBackgroundJob' &
WORKER1_PID=$!
./occ background-job:worker -v 'OC\TaskProcessing\SynchronousBackgroundJob' &
WORKER2_PID=$!
set +e
# Check for user admin: Shouldn't be there
OUT_ADMIN_ENGLISH_PROMPT_AI=$(./occ context_chat:prompt admin "Which factors are taken into account for the Ethical AI Rating?")
OUT_ADMIN_GERMAN_PROMPT_AI=$(./occ context_chat:prompt admin "Welche Faktoren beeinflussen das Ethical AI Rating?")
OUT_ADMIN_SEARCH_AI=$(./occ context_chat:search admin "Welche Faktoren beeinflussen das Ethical AI Rating?")
# Check for user test: Shouldn't be there
OUT_TEST_ENGLISH_PROMPT_AI=$(./occ context_chat:prompt test "Which factors are taken into account for the Ethical AI Rating?")
OUT_TEST_GERMAN_PROMPT_AI=$(./occ context_chat:prompt test "Welche Faktoren beeinflussen das Ethical AI Rating?")
OUT_TEST_SEARCH_AI=$(./occ context_chat:search test "Welche Faktoren beeinflussen das Ethical AI Rating?")
# Check for user test: Should be there, because it was shared
OUT_TEST_PROMPT_JOBS=$(./occ context_chat:prompt test "How do I set my TimedJob to be time insensitive?")
OUT_TEST_SEARCH_JOBS=$(./occ context_chat:search test "How do I set my TimedJob to be time insensitive?")
echo "OUT_ADMIN_ENGLISH_PROMPT_AI"
echo "$OUT_ADMIN_ENGLISH_PROMPT_AI"
echo "OUT_ADMIN_GERMAN_PROMPT_AI"
echo "$OUT_ADMIN_GERMAN_PROMPT_AI"
echo "OUT_ADMIN_SEARCH_AI"
echo "$OUT_ADMIN_SEARCH_AI"
echo "OUT_TEST_ENGLISH_PROMPT_AI"
echo "$OUT_TEST_ENGLISH_PROMPT_AI"
echo "OUT_TEST_GERMAN_PROMPT_AI"
echo "$OUT_TEST_GERMAN_PROMPT_AI"
echo "OUT_TEST_SEARCH_AI"
echo "$OUT_TEST_SEARCH_AI"
echo "OUT_TEST_PROMPT_JOBS"
echo "$OUT_TEST_PROMPT_JOBS"
echo "OUT_TEST_SEARCH_JOBS"
echo "$OUT_TEST_SEARCH_JOBS"
echo "$OUT_ADMIN_ENGLISH_PROMPT_AI" | grep -q -v "If all of these points are met, we give a Green label." && echo '✅ Admin does not see AI overview anymore' || exit 1
echo "$OUT_ADMIN_GERMAN_PROMPT_AI" | grep -q -v "If all of these points are met, we give a Green label." && echo '✅ Admin does not see AI overview anymore, after german question' || exit 1
echo "$OUT_ADMIN_SEARCH_AI" | grep -q -v "overview.rst" && echo '✅ Admin does not see AI overview anymore, when using search' || exit 1
echo "$OUT_TEST_ENGLISH_PROMPT_AI" | grep -q -v "If all of these points are met, we give a Green label." && echo '✅ Test user does not see AI overview' || exit 1
echo "$OUT_TEST_GERMAN_PROMPT_AI" | grep -q -v "If all of these points are met, we give a Green label." && echo '✅Test user does not see AI overview, after german question' || exit 1
echo "$OUT_TEST_SEARCH_AI" | grep -q -v "overview.rst" && echo '✅Test user does not see AI overview, when using search' || exit 1
echo "$OUT_TEST_PROMPT_JOBS" | grep -q "background jobs" && echo '✅Test user does see BackgroundJobs docs' || exit 1
echo "$OUT_TEST_SEARCH_JOBS" | grep -q "backgroundjobs.md" && echo '✅Test user does see BackgroundJobs docs' || exit 1
kill -9 $WORKER1_PID
kill -9 $WORKER2_PID
- name: Show nextcloud logs
if: always()
run: |
cat data/nextcloud.log
- name: Show context chat logs
if: always()
run: |
cat data/context_chat.log
- name: Show backend logs
if: always()
run: |
cat context_chat_backend/backend_logs || echo "No main backend logs"
cat context_chat_backend/em_backend_logs || echo "No embedding server logs"
echo '--------------------------------------------------'
tail -v -n +1 context_chat_backend/persistent_storage/logs/* || echo "No logs in logs directory"
summary:
permissions:
contents: none
runs-on: ubuntu-latest-low
needs: [scan-test, cron-test, listener-test]
if: always()
# This is the summary, we just avoid to rename it so that branch protection rules still match
name: integration-test
steps:
- name: Summary status
run: if ${{ needs.scan-test.rest != 'success' && needs.cron-test.result != 'success' && needs.listener-test.result != 'success' }}; then exit 1; fi