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
90 changes: 90 additions & 0 deletions .github/workflows/buddy-integration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: Buddy Integration

on:
workflow_dispatch:

jobs:
buddy-runtime:
name: Buddy runtime smoke (manual)
runs-on: ubuntu-22.04
timeout-minutes: 20
permissions:
contents: read
packages: read
env:
SEARCH_BUILD: MANTICORE
MANTICORE_IMAGE: manticoresearch/manticore@sha256:24835e1b590a31da0f45809b032865b1caab0a1b58f4ed14da9128a338f2d365

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: "8.3"
coverage: none
extensions: mysqli, pdo_mysql, mbstring
tools: composer:v2

- name: Start Manticore with Buddy extras
run: |
docker pull "$MANTICORE_IMAGE"
docker run -d --name searchd \
-e EXTRA=1 \
-p 9307:9306 \
-p 9312:9312 \
"$MANTICORE_IMAGE"

- name: Wait for searchd
run: |
n=0
while [ "$n" -lt 60 ]; do
if php -r '
try {
$pdo = new PDO("mysql:host=127.0.0.1;port=9307", "", "");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->query("SHOW TABLES");
exit(0);
} catch (Throwable $exception) {
exit(1);
}
' >/dev/null 2>&1; then
exit 0
fi
n=$((n + 1))
sleep 1
done
echo "searchd did not become SQL-ready on 127.0.0.1:9307"
docker logs searchd || true
exit 1

- name: Seed runtime test table
run: |
cat > /tmp/seed-buddy-rt.php <<'PHP'
<?php
$pdo = new PDO('mysql:host=127.0.0.1;port=9307', '', '');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec('CREATE TABLE IF NOT EXISTS rt(title text, content text, gid uint)');
$pdo->exec('TRUNCATE TABLE rt');
$pdo->exec("REPLACE INTO rt(id, title, content, gid) VALUES (1, 'test', 'teh words', 1)");
PHP
php /tmp/seed-buddy-rt.php

- name: Install dependencies
run: composer install --prefer-dist --no-interaction --no-progress

- name: Run Buddy-specific runtime tests (must not skip)
run: |
./vendor/bin/phpunit \
--configuration tests/travis/pdo.phpunit.xml \
--filter '/(testQSuggestExecutionWhenBuddySupported|testAutocompleteExecutionWhenBuddySupported)/' \
--fail-on-skipped

- name: Show searchd logs
if: always()
run: docker logs searchd || true

- name: Stop searchd container
if: always()
run: docker rm -f searchd || true
117 changes: 111 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,44 @@ jobs:
name: PHP ${{ matrix.php }} / ${{ matrix.driver }} / ${{ matrix.search_build }}
runs-on: ubuntu-22.04
timeout-minutes: 30
continue-on-error: ${{ matrix.search_build == 'SPHINX3' }}
permissions:
contents: read
packages: read
strategy:
fail-fast: false
matrix:
php: ['7.4', '8.0', '8.1']
php: ['8.2', '8.3']
driver: [mysqli, pdo]
search_build: [SPHINX2, SPHINX3, MANTICORE]
env:
DRIVER: ${{ matrix.driver }}
SEARCH_BUILD: ${{ matrix.search_build }}
COVERAGE_LANE: ${{ matrix.php == '8.3' && matrix.driver == 'pdo' && matrix.search_build == 'MANTICORE' }}

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup PHP
if: env.COVERAGE_LANE != 'true'
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
coverage: none
extensions: mysqli, pdo_mysql, mbstring
tools: composer:v2

- name: Setup PHP (coverage lane)
if: env.COVERAGE_LANE == 'true'
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
coverage: xdebug
extensions: mysqli, pdo_mysql, mbstring
tools: composer:v2

- name: Resolve search image and group exclusions
id: vars
run: |
Expand Down Expand Up @@ -91,25 +103,118 @@ jobs:
run: |
n=0
while [ "$n" -lt 60 ]; do
if (echo > /dev/tcp/127.0.0.1/9307) >/dev/null 2>&1; then
if php -r '
try {
$pdo = new PDO("mysql:host=127.0.0.1;port=9307", "", "");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->query("SHOW TABLES");
exit(0);
} catch (Throwable $exception) {
exit(1);
}
' >/dev/null 2>&1; then
exit 0
fi
n=$((n + 1))
sleep 1
done
echo "searchd did not become ready on 127.0.0.1:9307"
echo "searchd did not become SQL-ready on 127.0.0.1:9307"
docker logs searchd || true
exit 1

- name: Validate composer metadata
run: composer validate --strict --no-check-publish

- name: Install dependencies
run: composer update --prefer-dist --no-interaction
run: composer install --prefer-dist --no-interaction --no-progress

- name: Prepare autoload
run: composer dump-autoload

- name: Run PHPStan
if: env.COVERAGE_LANE == 'true'
run: |
set -o pipefail
mkdir -p static-analysis
./vendor/bin/phpstan analyse --configuration phpstan.neon.dist --memory-limit=1G --no-progress --error-format=raw 2>&1 | tee static-analysis/phpstan.txt

- name: Run tests
run: |
./vendor/bin/phpunit --configuration "tests/travis/${DRIVER}.phpunit.xml" --coverage-text ${{ steps.vars.outputs.exclude_group }}
if [ "${COVERAGE_LANE}" = "true" ]; then
mkdir -p coverage
./vendor/bin/phpunit --configuration "tests/travis/${DRIVER}.phpunit.xml" --coverage-text --coverage-clover coverage/clover.xml ${{ steps.vars.outputs.exclude_group }}
else
./vendor/bin/phpunit --configuration "tests/travis/${DRIVER}.phpunit.xml" --coverage-text ${{ steps.vars.outputs.exclude_group }}
fi

- name: Build changed-line coverage artifact
if: always() && env.COVERAGE_LANE == 'true'
continue-on-error: true
run: |
mkdir -p coverage-artifact

BASE_SHA=""
BASE_LABEL=""

if [ "${{ github.event_name }}" = "pull_request" ]; then
BASE_SHA="${{ github.event.pull_request.base.sha }}"
BASE_LABEL="PR base (${BASE_SHA})"
else
BASE_SHA="${{ github.event.before }}"
BASE_LABEL="push before (${BASE_SHA})"
fi

if [ -z "${BASE_SHA}" ] \
|| [ "${BASE_SHA}" = "0000000000000000000000000000000000000000" ] \
|| ! git cat-file -e "${BASE_SHA}^{commit}" 2>/dev/null; then
DEFAULT_BRANCH="${{ github.event.repository.default_branch }}"
if git show-ref --verify --quiet "refs/remotes/origin/${DEFAULT_BRANCH}"; then
BASE_SHA="$(git merge-base "origin/${DEFAULT_BRANCH}" HEAD)"
BASE_LABEL="merge-base (origin/${DEFAULT_BRANCH})"
elif git cat-file -e "HEAD~1^{commit}" 2>/dev/null; then
BASE_SHA="$(git rev-parse HEAD~1)"
BASE_LABEL="fallback (HEAD~1)"
else
BASE_SHA="$(git rev-parse HEAD)"
BASE_LABEL="fallback (HEAD)"
fi
fi

git diff --unified=0 "${BASE_SHA}"...HEAD > coverage-artifact/changed-lines.patch || true
git diff --name-only "${BASE_SHA}"...HEAD > coverage-artifact/changed-files.txt || true

ADDED_LINES="$(git diff --numstat "${BASE_SHA}"...HEAD | awk '{a+=$1} END {print a+0}')"
REMOVED_LINES="$(git diff --numstat "${BASE_SHA}"...HEAD | awk '{d+=$2} END {print d+0}')"
CHANGED_FILES="$(wc -l < coverage-artifact/changed-files.txt | tr -d ' ')"

{
echo "Changed-line coverage artifact summary"
echo "Event: ${{ github.event_name }}"
echo "Base: ${BASE_LABEL}"
echo "Head: $(git rev-parse HEAD)"
echo "Changed files: ${CHANGED_FILES}"
echo "Added lines: ${ADDED_LINES}"
echo "Removed lines: ${REMOVED_LINES}"
if [ -f coverage/clover.xml ]; then
echo "Clover XML: coverage/clover.xml"
else
echo "Clover XML: missing"
fi
} > coverage-artifact/summary.txt

- name: Upload changed-line coverage artifact
if: always() && env.COVERAGE_LANE == 'true'
continue-on-error: true
uses: actions/upload-artifact@v4
with:
name: changed-line-coverage-php${{ matrix.php }}-${{ matrix.driver }}-${{ matrix.search_build }}
if-no-files-found: warn
path: |
coverage/clover.xml
static-analysis/phpstan.txt
coverage-artifact/summary.txt
coverage-artifact/changed-lines.patch
coverage-artifact/changed-files.txt

- name: Upload debug artifacts on failure
if: failure()
Expand Down
76 changes: 76 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: Documentation

on:
workflow_dispatch:
pull_request:
paths:
- docs/**
- README.md
- .github/workflows/docs.yml
push:
paths:
- docs/**
- README.md
- .github/workflows/docs.yml

permissions:
contents: read

concurrency:
group: docs-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Configure GitHub Pages
if: github.event_name == 'push' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
uses: actions/configure-pages@v5

- name: Install docs dependencies
run: |
python -m pip install --upgrade pip
pip install -r docs/requirements.txt

- name: Build docs
run: sphinx-build --fail-on-warning --keep-going -b html docs docs/_build/html

- name: Upload docs artifact (PR/debug)
if: always()
uses: actions/upload-artifact@v4
with:
name: docs-html
path: docs/_build/html
if-no-files-found: error

- name: Upload Pages artifact
if: github.event_name == 'push' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
uses: actions/upload-pages-artifact@v3
with:
path: docs/_build/html

deploy:
if: github.event_name == 'push' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
needs: build
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}

steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
1 change: 1 addition & 0 deletions .github/workflows/publish-search-images.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ on:
- tests/sphinx.conf
- tests/manticore.conf
- tests/test_udf.c
- tests/s3_test_udf.c
- tests/ms_test_udf.c

permissions:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ tests/searchd.pid
tests/data/rt.*
tests/data/test_udf.so
vendor/
.phpstan/
27 changes: 27 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,30 @@
#### 4.0.0
* Dropped support for PHP 8.1 and lower (minimum PHP is now 8.2)
* Updated CI PHP matrix to 8.2 and 8.3
* Normalized MySQLi driver exception handling for modern PHP `mysqli_sql_exception` behavior
* Hardened runtime validation for `SphinxQL`, `Facet`, `Helper`, and `Percolate` input contracts (fail-fast exceptions for invalid query-shape input)
* Standardized driver exception message prefixes for better diagnostics (`[mysqli][...]`, `[pdo][...]`)
* Expanded helper runtime API coverage (`SHOW WARNINGS`, `SHOW STATUS`, `SHOW INDEX STATUS`, `FLUSH RAMCHUNK`, `FLUSH RTINDEX`, `OPTIMIZE INDEX`, UDF lifecycle checks)
* Added fluent boolean grouping APIs (`orWhere`, `whereOpen/whereClose`, `orHaving`, `havingOpen/havingClose`) and JOIN builders (`join`, `innerJoin`, `leftJoin`, `rightJoin`, `crossJoin`)
* Added `orderByKnn()` and broader helper wrappers for operational and Manticore-oriented commands (`SHOW PROFILE/PLAN/THREADS/VERSION/PLUGINS`, table status/settings/indexes, flush/reload/kill, suggest family)
* Added capability discovery and feature-gating APIs (`Capabilities`, `getCapabilities()`, `supports()`, `requireSupport()`) with `UnsupportedFeatureException` for unsupported command families
* Added `SphinxQL::requireSupport()` passthrough and convenience engine predicates on `Capabilities` (`isManticore`, `isSphinx2`, `isSphinx3`)
* Added helper parity wrappers for `SHOW CHARACTER SET` and `SHOW COLLATION`
* Added `docs/feature-matrix.yml` as a feature-level support map across Sphinx2/Sphinx3/Manticore
* Added capability-aware runtime tests for optional engine features (`supportsCommand`, Buddy-gated checks)
* Added and stabilized Sphinx 3 compatibility coverage while preserving Sphinx 2 and Manticore test behavior
* Added support for optional connection credentials (`username`/`password`) in both PDO and MySQLi drivers (closes #208)
* Added optional-index `update($index = null)` flow for fluent `->update()->into($index)` usage (closes #184)
* Added explicit `update()->compile()/execute()` guard when no target index is set via `into($index)` (prevents invalid `UPDATE` SQL emission)
* Restored `showTables($index = null)` compatibility (`SHOW TABLES` for null/empty, `SHOW TABLES LIKE ...` for non-empty) and removed hardcoded `rt` assumptions from runtime capability probes
* Aligned Buddy capability flags so `callQSuggest()`/`callAutocomplete()` are gated by detected Buddy availability
* Added MVA insert/update array example in README (closes #178)
* Corrected escaping docs to reference connection-level helpers and clarified `quoteIdentifier()` availability (closes #203)
* Added a root `LICENSE` file (closes #171)
* Migrated CI to GitHub Actions-only validation with strict composer metadata checks
* Hardened GitHub Actions reliability with SQL-readiness checks, full-history checkout for changed-line artifacts, and digest-pinned Buddy integration runtime image
* Updated documentation and added a dedicated `MIGRATING-4.0.md` guide

#### 3.0.2
* Dropped support for PHP 7.3 and lower

Expand Down
Loading