From 8fe465dd751cd22d99ca55c66d14bf2a44f0255b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gamez?=
Date: Thu, 12 Feb 2026 10:08:13 +0100
Subject: [PATCH 1/3] Add Dependabot updates for docs dependencies
---
.github/dependabot.yml | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 4bf631b5..c851e7c3 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -13,4 +13,16 @@ updates:
prefix: "github-actions"
open-pull-requests-limit: 10
labels:
- - "dependency"
+ - "dependencies"
+
+ - package-ecosystem: "pip"
+ directory: "/docs"
+ schedule:
+ interval: "weekly"
+ day: "monday"
+ commit-message:
+ include: "scope"
+ prefix: "docs-deps"
+ open-pull-requests-limit: 10
+ labels:
+ - "dependencies"
From f49052e0cfd2ccc45b87baff970de556e2137c24 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gamez?=
Date: Thu, 12 Feb 2026 09:42:02 +0100
Subject: [PATCH 2/3] Refactor CI pipeline
---
.github/workflows/backward-compatibility.yml | 45 ---
.github/workflows/ci.yml | 277 ++++++++++++++++
.github/workflows/docs.yml | 21 +-
.github/workflows/emulator-tests.yml | 102 ------
.github/workflows/grpc-tests.yml | 127 -------
.github/workflows/integration-tests.yml | 86 -----
.github/workflows/secure-tests.yml | 331 +++++++++++++++++++
.github/workflows/static-analysis.yml | 60 ----
.github/workflows/tests.yml | 85 -----
README.md | 6 +-
docs/index.rst | 6 +-
11 files changed, 625 insertions(+), 521 deletions(-)
delete mode 100644 .github/workflows/backward-compatibility.yml
create mode 100644 .github/workflows/ci.yml
delete mode 100644 .github/workflows/emulator-tests.yml
delete mode 100644 .github/workflows/grpc-tests.yml
delete mode 100644 .github/workflows/integration-tests.yml
create mode 100644 .github/workflows/secure-tests.yml
delete mode 100644 .github/workflows/static-analysis.yml
delete mode 100644 .github/workflows/tests.yml
diff --git a/.github/workflows/backward-compatibility.yml b/.github/workflows/backward-compatibility.yml
deleted file mode 100644
index 2a0254cd..00000000
--- a/.github/workflows/backward-compatibility.yml
+++ /dev/null
@@ -1,45 +0,0 @@
-name: Backward Compatibility Check
-
-on:
- pull_request:
- branches: ['8.x']
- paths:
- - 'src/**'
- - 'composer.json'
- - '.github/workflows/backward-compatibility.yml'
- push:
- branches: ['8.x']
- paths:
- - 'src/**'
- - 'composer.json'
- - '.github/workflows/backward-compatibility.yml'
- workflow_dispatch:
-
-permissions:
- contents: read
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
- cancel-in-progress: true
-
-jobs:
- bc-checks:
- name: Backward Compatibility Check
- runs-on: ubuntu-latest
-
- steps:
- - uses: actions/checkout@v6
- with:
- fetch-depth: 0
-
- - name: Install PHP
- uses: shivammathur/setup-php@v2
- with:
- php-version: 8.3
- extensions: grpc
-
- - name: Install roave/backward-compatibility-check
- run: composer require --dev roave/backward-compatibility-check
-
- - name: Check for BC breaks
- run: vendor/bin/roave-backward-compatibility-check --format=github-actions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 00000000..e38dacbb
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,277 @@
+name: CI
+
+on:
+ pull_request:
+ paths:
+ - "src/**"
+ - "tests/**"
+ - "composer.json"
+ - "phpstan.neon.dist"
+ - "phpunit.xml.dist"
+ - ".php-cs-fixer.dist.php"
+ - "rector.php"
+ - "composer-dependency-analyser.php"
+ - ".github/workflows/ci.yml"
+ - ".github/workflows/secure-tests.yml"
+ push:
+ branches: ['8.x']
+ paths:
+ - "src/**"
+ - "tests/**"
+ - "composer.json"
+ - "phpstan.neon.dist"
+ - "phpunit.xml.dist"
+ - ".php-cs-fixer.dist.php"
+ - "rector.php"
+ - "composer-dependency-analyser.php"
+ - ".github/workflows/ci.yml"
+ - ".github/workflows/secure-tests.yml"
+ workflow_dispatch:
+
+permissions:
+ contents: read
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ dependency-validation:
+ name: Dependency Validation
+ runs-on: ubuntu-latest
+ timeout-minutes: 20
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v6
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: "8.5"
+ coverage: none
+ tools: composer
+
+ - name: Get Composer cache directory
+ id: composer-cache
+ shell: bash
+ run: |
+ echo "dir=$(composer config cache-files-dir)" >> "$GITHUB_OUTPUT"
+
+ - name: Cache Composer cache directory
+ uses: actions/cache@v5
+ with:
+ path: ${{ steps.composer-cache.outputs.dir }}
+ key: ${{ runner.os }}-composer-${{ hashFiles('composer.json', 'composer.lock') }}
+ restore-keys: ${{ runner.os }}-composer-
+
+ - name: Validate composer.json
+ run: composer validate --strict
+
+ - name: Ensure dependencies can be installed
+ run: composer install --no-interaction --no-progress --ansi --dry-run --ignore-platform-req=ext-grpc
+
+ static-analysis:
+ name: "PHPStan (PHP ${{ matrix.php }})"
+ needs:
+ - dependency-validation
+ runs-on: ubuntu-latest
+ timeout-minutes: 20
+
+ strategy:
+ fail-fast: false
+ matrix:
+ php:
+ - "8.3"
+ - "8.4"
+ - "8.5"
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v6
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php }}
+ tools: composer, pecl
+ coverage: none
+
+ - name: Get Composer cache directory
+ id: composer-cache
+ shell: bash
+ run: |
+ echo "dir=$(composer config cache-files-dir)" >> "$GITHUB_OUTPUT"
+
+ - name: Cache Composer cache directory
+ uses: actions/cache@v5
+ with:
+ path: ${{ steps.composer-cache.outputs.dir }}
+ key: ${{ runner.os }}-composer-${{ hashFiles('composer.json', 'composer.lock') }}
+ restore-keys: ${{ runner.os }}-composer-
+
+ - name: Install dependencies with Composer
+ run: composer install --no-interaction --no-progress --ansi --ignore-platform-req=ext-grpc
+
+ - name: Setup problem matchers for PHP
+ run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
+
+ - name: Run PHPStan
+ run: XDEBUG_MODE=off vendor/bin/phpstan analyse --no-progress --error-format=github
+
+ tests:
+ name: "PHP ${{ matrix.php }}, ${{ matrix.dependencies }} deps"
+ needs:
+ - static-analysis
+ runs-on: ubuntu-latest
+ timeout-minutes: 20
+
+ strategy:
+ fail-fast: false
+ matrix:
+ php:
+ - "8.3"
+ - "8.4"
+ - "8.5"
+ dependencies:
+ - "lowest"
+ - "highest"
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v6
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php }}
+ tools: composer, pecl
+ coverage: none
+
+ - name: Get Composer cache directory
+ id: composer-cache
+ shell: bash
+ run: |
+ echo "dir=$(composer config cache-files-dir)" >> "$GITHUB_OUTPUT"
+
+ - name: Cache Composer cache directory
+ uses: actions/cache@v5
+ with:
+ path: ${{ steps.composer-cache.outputs.dir }}
+ key: ${{ runner.os }}-composer-${{ hashFiles('composer.json', 'composer.lock') }}
+ restore-keys: ${{ runner.os }}-composer-
+
+ - name: Install dependencies with Composer
+ run: |
+ if [ "${{ matrix.dependencies }}" = "lowest" ]; then
+ composer update --prefer-lowest --prefer-stable --no-interaction --no-progress --ansi --ignore-platform-req=ext-grpc
+ else
+ composer update --no-interaction --no-progress --ansi --ignore-platform-req=ext-grpc
+ fi
+
+ - name: Setup problem matchers for PHP
+ run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
+
+ - name: Setup Problem Matchers for PHPUnit
+ run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
+
+ - name: Run PHPUnit
+ run: vendor/bin/phpunit --testsuite=unit --testdox
+
+ code-coverage:
+ name: Unit Test Coverage (PHP 8.5)
+ needs:
+ - tests
+ runs-on: ubuntu-latest
+ timeout-minutes: 20
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v6
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: "8.5"
+ tools: composer, pecl
+ coverage: xdebug
+
+ - name: Get Composer cache directory
+ id: composer-cache
+ shell: bash
+ run: |
+ echo "dir=$(composer config cache-files-dir)" >> "$GITHUB_OUTPUT"
+
+ - name: Cache Composer cache directory
+ uses: actions/cache@v5
+ with:
+ path: ${{ steps.composer-cache.outputs.dir }}
+ key: ${{ runner.os }}-composer-${{ hashFiles('composer.json', 'composer.lock') }}
+ restore-keys: ${{ runner.os }}-composer-
+
+ - name: Install dependencies with Composer
+ run: composer install --no-interaction --no-progress --ansi --ignore-platform-req=ext-grpc
+
+ - name: Setup problem matchers for PHP
+ run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
+
+ - name: Setup Problem Matchers for PHPUnit
+ run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
+
+ - name: Run PHPUnit with coverage
+ run: vendor/bin/phpunit --testsuite=unit --coverage-clover=coverage.xml --log-junit=test-report.xml --testdox
+
+ - name: Upload test results to Codecov
+ if: ${{ !cancelled() }}
+ uses: codecov/codecov-action@v5
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+ flags: unit
+ report_type: test_results
+ fail_ci_if_error: false
+
+ - name: Upload coverage to Codecov
+ if: ${{ !cancelled() }}
+ uses: codecov/codecov-action@v5
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+ files: ./coverage.xml
+ flags: unit
+ fail_ci_if_error: false
+
+ bc-check:
+ name: Backward Compatibility Check
+ needs:
+ - dependency-validation
+ runs-on: ubuntu-latest
+ timeout-minutes: 20
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v6
+ with:
+ fetch-depth: 0
+ fetch-tags: true
+
+ - name: "Workaround: Configure Git safe.directory for roave-bc-check Docker action"
+ run: |
+ mkdir -p /home/runner/work/_temp/_github_home
+ printf "[safe]\n\tdirectory = /github/workspace\n" > /home/runner/work/_temp/_github_home/.gitconfig
+
+ - name: Check whether repository has tags
+ id: check-tags
+ shell: bash
+ run: |
+ if git tag --list | grep -q .; then
+ echo "has_tags=true" >> "$GITHUB_OUTPUT"
+ else
+ echo "has_tags=false" >> "$GITHUB_OUTPUT"
+ fi
+
+ - name: Run Roave BC Check
+ if: ${{ steps.check-tags.outputs.has_tags == 'true' }}
+ uses: docker://nyholm/roave-bc-check-ga
+
+ - name: Skip Roave BC Check (no tags found)
+ if: ${{ steps.check-tags.outputs.has_tags != 'true' }}
+ run: echo "Skipping BC check because no git tags were found."
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index ef01822f..991c7841 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -3,19 +3,19 @@ name: Check links
on:
pull_request:
paths:
- - 'docs/**'
- - '.github/workflows/docs.yml'
- - 'CHANGELOG.md'
- - 'README.md'
- - 'lychee.toml'
+ - "docs/**"
+ - ".github/workflows/docs.yml"
+ - "CHANGELOG.md"
+ - "README.md"
+ - "lychee.toml"
push:
branches: ['8.x']
paths:
- - 'docs/**'
- - '.github/workflows/docs.yml'
- - 'CHANGELOG.md'
- - 'README.md'
- - 'lychee.toml'
+ - "docs/**"
+ - ".github/workflows/docs.yml"
+ - "CHANGELOG.md"
+ - "README.md"
+ - "lychee.toml"
release:
types: [published]
workflow_dispatch:
@@ -31,6 +31,7 @@ jobs:
links:
name: Check Links
runs-on: ubuntu-latest
+ timeout-minutes: 20
steps:
- name: Checkout repository
diff --git a/.github/workflows/emulator-tests.yml b/.github/workflows/emulator-tests.yml
deleted file mode 100644
index a604ea99..00000000
--- a/.github/workflows/emulator-tests.yml
+++ /dev/null
@@ -1,102 +0,0 @@
-name: Emulator Tests
-
-on:
- pull_request_target:
- types: [ opened, synchronize, reopened ]
- paths:
- - 'src/**'
- - 'tests/**'
- - '.github/workflows/emulator-tests.yml'
- - 'composer.json'
- - 'phpstan.neon.dist'
- push:
- branches: ['8.x']
- paths:
- - 'src/**'
- - 'tests/**'
- - '.github/workflows/emulator-tests.yml'
- - 'composer.json'
- - 'phpstan.neon.dist'
- workflow_dispatch:
-
-permissions:
- contents: read
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
- cancel-in-progress: true
-
-jobs:
- emulator-tests:
- name: Emulator Tests
- runs-on: ubuntu-latest
-
- env:
- php-version: '8.5'
-
- steps:
- - name: Checkout code
- uses: actions/checkout@v6
- with:
- ref: ${{ (github.event_name == 'pull_request_target' && github.event.pull_request.head.sha) || github.sha }}
-
- - name: Setup PHP
- uses: shivammathur/setup-php@v2
- with:
- php-version: ${{ env.php-version }}
- tools: composer, pecl
- coverage: xdebug
-
- - name: Setup problem matchers for PHP
- run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
-
- - uses: "ramsey/composer-install@v3"
- with:
- composer-options: "--ignore-platform-req=ext-grpc"
-
- - name: Setup Problem Matchers for PHPUnit
- run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
-
- - name: Set Up Node
- uses: actions/setup-node@v6
- with:
- node-version: '24'
-
- - name: Set Up Java
- uses: actions/setup-java@v5.2.0
- with:
- distribution: 'temurin'
- java-version: '21'
-
- - name: Install Firebase Tools
- run: npm install -g firebase-tools
-
- - name: Run emulated Integration Tests
- env:
- GOOGLE_APPLICATION_CREDENTIALS: ${{secrets.GOOGLE_APPLICATION_CREDENTIALS}}
- TEST_FIREBASE_APP_ID: ${{secrets.TEST_FIREBASE_APP_ID}}
- TEST_FIREBASE_RTDB_URI: ${{secrets.TEST_FIREBASE_RTDB_URI}}
- TEST_FIREBASE_TENANT_ID: ${{secrets.TEST_FIREBASE_TENANT_ID}}
- TEST_REGISTRATION_TOKENS: ${{secrets.TEST_REGISTRATION_TOKENS}}
- FIREBASE_DATABASE_EMULATOR_HOST: localhost:9100
- FIREBASE_AUTH_EMULATOR_HOST: localhost:9099
- XDEBUG_MODE: coverage
- run: firebase emulators:exec --only auth,database --project beste-firebase 'XDEBUG_MODE=coverage vendor/bin/phpunit --group=emulator --exclude-group grpc --coverage-clover=coverage.xml --log-junit=test-report.xml'
-
- - name: Upload test results to Codecov
- if: ${{ !cancelled() }}
- uses: codecov/codecov-action@v5
- with:
- token: ${{ secrets.CODECOV_TOKEN }}
- flags: emulator
- report_type: test_results
- fail_ci_if_error: false
-
- - name: Upload coverage to Codecov
- if: ${{ !cancelled() }}
- uses: codecov/codecov-action@v5
- with:
- token: ${{ secrets.CODECOV_TOKEN }}
- files: ./coverage.xml
- flags: emulator
- fail_ci_if_error: false
diff --git a/.github/workflows/grpc-tests.yml b/.github/workflows/grpc-tests.yml
deleted file mode 100644
index 99c93042..00000000
--- a/.github/workflows/grpc-tests.yml
+++ /dev/null
@@ -1,127 +0,0 @@
-name: gRPC Tests
-
-on:
- pull_request_target:
- types: [opened, synchronize, reopened]
- paths:
- - 'src/**'
- - 'tests/**'
- - '.github/workflows/grpc-tests.yml'
- - 'composer.json'
- - 'phpstan.neon.dist'
- push:
- branches: ['8.x']
- paths:
- - 'src/**'
- - 'tests/**'
- - '.github/workflows/grpc-tests.yml'
- - 'composer.json'
- - 'phpstan.neon.dist'
- workflow_dispatch:
-
-permissions:
- contents: read
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
- cancel-in-progress: true
-
-jobs:
- grpc-tests:
- name: gRPC Tests (PHP 8.5)
- runs-on: ubuntu-latest
- # Non-blocking while the gRPC extension is broken/unstable on PHP 8.5.
- # See https://github.com/shivammathur/setup-php/issues/1041.
- # Remove this once upstream releases a stable extension and tests pass.
- continue-on-error: true
- if: ${{ github.event_name != 'pull_request_target' || github.event.pull_request.head.repo.full_name == github.repository }}
-
- env:
- key: cache-grpc
- php-version: 8.5
- extensions: grpc
-
- steps:
- - name: Checkout code
- uses: actions/checkout@v6
- with:
- ref: ${{ (github.event_name == 'pull_request_target' && github.event.pull_request.head.sha) || github.sha }}
-
- - name: Setup cache environment
- id: extcache
- uses: shivammathur/cache-extensions@v1
- with:
- php-version: ${{ env.php-version }}
- extensions: ${{ env.extensions }}
- key: ${{ env.key }}
-
- - name: Cache extensions
- uses: actions/cache@v5.0.3
- with:
- path: ${{ steps.extcache.outputs.dir }}
- key: ${{ steps.extcache.outputs.key }}
- restore-keys: ${{ steps.extcache.outputs.key }}
-
- - name: Setup PHP
- uses: shivammathur/setup-php@v2
- with:
- php-version: ${{ env.php-version }}
- extensions: ${{ env.extensions }}
- ini-values: grpc.grpc_verbosity=error, grpc.grpc_trace=
- tools: composer, pecl
- coverage: xdebug
-
- - name: Setup problem matchers for PHP
- run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
-
- - name: Verify gRPC extension
- id: grpc
- run: php -m | grep -i '^grpc$'
-
- - uses: "ramsey/composer-install@v3"
- id: composer
- if: ${{ steps.grpc.outcome == 'success' }}
-
- - name: Setup Problem Matchers for PHPUnit
- run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
-
- - name: Run gRPC Tests
- id: grpc-tests
- if: ${{ steps.grpc.outcome == 'success' }}
- env:
- GOOGLE_APPLICATION_CREDENTIALS: ${{secrets.GOOGLE_APPLICATION_CREDENTIALS}}
- TEST_FIREBASE_APP_ID: ${{secrets.TEST_FIREBASE_APP_ID}}
- TEST_FIREBASE_RTDB_URI: ${{secrets.TEST_FIREBASE_RTDB_URI}}
- TEST_FIREBASE_TENANT_ID: ${{secrets.TEST_FIREBASE_TENANT_ID}}
- TEST_REGISTRATION_TOKENS: ${{secrets.TEST_REGISTRATION_TOKENS}}
- XDEBUG_MODE: coverage
- run: vendor/bin/phpunit --testsuite=integration --group grpc --coverage-clover=coverage.xml --log-junit=test-report.xml --testdox
-
- - name: Summarize gRPC failures
- if: ${{ always() && (steps.grpc.outcome == 'failure' || steps.grpc-tests.outcome == 'failure') }}
- run: |
- echo "::notice::gRPC tests are non-blocking due to missing/broken gRPC on PHP 8.5."
- {
- echo "### gRPC tests are non-blocking"
- echo
- echo "gRPC extension was not available or gRPC tests failed (likely due to missing/broken gRPC on PHP 8.5)."
- echo "See https://github.com/shivammathur/setup-php/issues/1041."
- } >> "$GITHUB_STEP_SUMMARY"
-
- - name: Upload test results to Codecov
- if: ${{ !cancelled() && steps.grpc.outcome == 'success' }}
- uses: codecov/codecov-action@v5
- with:
- token: ${{ secrets.CODECOV_TOKEN }}
- flags: grpc
- report_type: test_results
- fail_ci_if_error: false
-
- - name: Upload coverage to Codecov
- if: ${{ !cancelled() && steps.grpc.outcome == 'success' }}
- uses: codecov/codecov-action@v5
- with:
- token: ${{ secrets.CODECOV_TOKEN }}
- files: ./coverage.xml
- flags: grpc
- fail_ci_if_error: false
diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
deleted file mode 100644
index efada7d8..00000000
--- a/.github/workflows/integration-tests.yml
+++ /dev/null
@@ -1,86 +0,0 @@
-name: Integration Tests
-
-on:
- pull_request_target:
- types: [opened, synchronize, reopened]
- paths:
- - 'src/**'
- - 'tests/**'
- - '.github/workflows/integration-tests.yml'
- - 'composer.json'
- - 'phpstan.neon.dist'
- push:
- branches: ['8.x']
- paths:
- - 'src/**'
- - 'tests/**'
- - '.github/workflows/integration-tests.yml'
- - 'composer.json'
- - 'phpstan.neon.dist'
- workflow_dispatch:
-
-permissions:
- contents: read
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
- cancel-in-progress: true
-
-jobs:
- integration-tests:
- name: Integration Tests
- runs-on: ubuntu-latest
-
- env:
- php-version: '8.5'
-
- steps:
- - name: Checkout code
- uses: actions/checkout@v6
- with:
- ref: ${{ (github.event_name == 'pull_request_target' && github.event.pull_request.head.sha) || github.sha }}
-
- - name: Setup PHP
- uses: shivammathur/setup-php@v2
- with:
- php-version: ${{ env.php-version }}
- tools: composer, pecl
- coverage: xdebug
-
- - name: Setup problem matchers for PHP
- run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
-
- - uses: "ramsey/composer-install@v3"
- with:
- composer-options: "--ignore-platform-req=ext-grpc"
-
- - name: Setup Problem Matchers for PHPUnit
- run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
-
- - name: Run Integration Tests
- env:
- GOOGLE_APPLICATION_CREDENTIALS: ${{secrets.GOOGLE_APPLICATION_CREDENTIALS}}
- TEST_FIREBASE_APP_ID: ${{secrets.TEST_FIREBASE_APP_ID}}
- TEST_FIREBASE_RTDB_URI: ${{secrets.TEST_FIREBASE_RTDB_URI}}
- TEST_FIREBASE_TENANT_ID: ${{secrets.TEST_FIREBASE_TENANT_ID}}
- TEST_REGISTRATION_TOKENS: ${{secrets.TEST_REGISTRATION_TOKENS}}
- XDEBUG_MODE: coverage
- run: vendor/bin/phpunit --testsuite=integration --exclude-group grpc --coverage-clover=coverage.xml --log-junit=test-report.xml --testdox
-
- - name: Upload test results to Codecov
- if: ${{ !cancelled() }}
- uses: codecov/codecov-action@v5
- with:
- token: ${{ secrets.CODECOV_TOKEN }}
- flags: integration
- report_type: test_results
- fail_ci_if_error: false
-
- - name: Upload coverage to Codecov
- if: ${{ !cancelled() }}
- uses: codecov/codecov-action@v5
- with:
- token: ${{ secrets.CODECOV_TOKEN }}
- files: ./coverage.xml
- flags: integration
- fail_ci_if_error: false
diff --git a/.github/workflows/secure-tests.yml b/.github/workflows/secure-tests.yml
new file mode 100644
index 00000000..61fb7032
--- /dev/null
+++ b/.github/workflows/secure-tests.yml
@@ -0,0 +1,331 @@
+name: Secure Tests
+
+on:
+ workflow_run:
+ workflows: ["CI"]
+ types: [completed]
+ workflow_dispatch:
+
+permissions:
+ contents: read
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch || github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ dependency-validation:
+ name: Dependency Validation
+ runs-on: ubuntu-latest
+ timeout-minutes: 20
+ if: ${{ github.event_name == 'workflow_dispatch' || (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.head_repository.full_name == github.repository) }}
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v6
+ with:
+ ref: ${{ github.event.workflow_run.head_sha || github.sha }}
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: "8.5"
+ coverage: none
+ tools: composer
+
+ - name: Get Composer cache directory
+ id: composer-cache
+ shell: bash
+ run: |
+ echo "dir=$(composer config cache-files-dir)" >> "$GITHUB_OUTPUT"
+
+ - name: Cache Composer cache directory
+ uses: actions/cache@v5
+ with:
+ path: ${{ steps.composer-cache.outputs.dir }}
+ key: ${{ runner.os }}-composer-${{ hashFiles('composer.json', 'composer.lock') }}
+ restore-keys: ${{ runner.os }}-composer-
+
+ - name: Validate composer.json
+ run: composer validate --strict
+
+ - name: Ensure dependencies can be installed
+ run: composer install --no-interaction --no-progress --ansi --dry-run --ignore-platform-req=ext-grpc
+
+ integration-tests:
+ name: Integration Tests
+ needs:
+ - dependency-validation
+ runs-on: ubuntu-latest
+ timeout-minutes: 20
+
+ env:
+ php-version: '8.5'
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v6
+ with:
+ ref: ${{ github.event.workflow_run.head_sha || github.sha }}
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ env.php-version }}
+ tools: composer, pecl
+ coverage: xdebug
+
+ - name: Setup problem matchers for PHP
+ run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
+
+ - name: Get Composer cache directory
+ id: composer-cache
+ shell: bash
+ run: |
+ echo "dir=$(composer config cache-files-dir)" >> "$GITHUB_OUTPUT"
+
+ - name: Cache Composer cache directory
+ uses: actions/cache@v5
+ with:
+ path: ${{ steps.composer-cache.outputs.dir }}
+ key: ${{ runner.os }}-composer-${{ hashFiles('composer.json', 'composer.lock') }}
+ restore-keys: ${{ runner.os }}-composer-
+
+ - name: Install dependencies with Composer
+ run: composer install --no-interaction --no-progress --ansi --ignore-platform-req=ext-grpc
+
+ - name: Setup Problem Matchers for PHPUnit
+ run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
+
+ - name: Run Integration Tests
+ env:
+ GOOGLE_APPLICATION_CREDENTIALS: ${{secrets.GOOGLE_APPLICATION_CREDENTIALS}}
+ TEST_FIREBASE_APP_ID: ${{secrets.TEST_FIREBASE_APP_ID}}
+ TEST_FIREBASE_RTDB_URI: ${{secrets.TEST_FIREBASE_RTDB_URI}}
+ TEST_FIREBASE_TENANT_ID: ${{secrets.TEST_FIREBASE_TENANT_ID}}
+ TEST_REGISTRATION_TOKENS: ${{secrets.TEST_REGISTRATION_TOKENS}}
+ XDEBUG_MODE: coverage
+ run: vendor/bin/phpunit --testsuite=integration --exclude-group grpc --coverage-clover=coverage.xml --log-junit=test-report.xml --testdox
+
+ - name: Upload integration test results to Codecov
+ if: ${{ !cancelled() }}
+ uses: codecov/codecov-action@v5
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+ flags: integration
+ report_type: test_results
+ fail_ci_if_error: false
+
+ - name: Upload integration coverage to Codecov
+ if: ${{ !cancelled() }}
+ uses: codecov/codecov-action@v5
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+ files: ./coverage.xml
+ flags: integration
+ fail_ci_if_error: false
+
+ emulator-tests:
+ name: Emulator Tests
+ needs:
+ - dependency-validation
+ runs-on: ubuntu-latest
+ timeout-minutes: 20
+
+ env:
+ php-version: '8.5'
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v6
+ with:
+ ref: ${{ github.event.workflow_run.head_sha || github.sha }}
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ env.php-version }}
+ tools: composer, pecl
+ coverage: xdebug
+
+ - name: Setup problem matchers for PHP
+ run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
+
+ - name: Get Composer cache directory
+ id: composer-cache
+ shell: bash
+ run: |
+ echo "dir=$(composer config cache-files-dir)" >> "$GITHUB_OUTPUT"
+
+ - name: Cache Composer cache directory
+ uses: actions/cache@v5
+ with:
+ path: ${{ steps.composer-cache.outputs.dir }}
+ key: ${{ runner.os }}-composer-${{ hashFiles('composer.json', 'composer.lock') }}
+ restore-keys: ${{ runner.os }}-composer-
+
+ - name: Install dependencies with Composer
+ run: composer install --no-interaction --no-progress --ansi --ignore-platform-req=ext-grpc
+
+ - name: Setup Problem Matchers for PHPUnit
+ run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
+
+ - name: Set Up Node
+ uses: actions/setup-node@v6
+ with:
+ node-version: '24'
+
+ - name: Set Up Java
+ uses: actions/setup-java@v5.2.0
+ with:
+ distribution: 'temurin'
+ java-version: '21'
+
+ - name: Install Firebase Tools
+ run: npm install -g firebase-tools
+
+ - name: Run emulated Integration Tests
+ env:
+ GOOGLE_APPLICATION_CREDENTIALS: ${{secrets.GOOGLE_APPLICATION_CREDENTIALS}}
+ TEST_FIREBASE_APP_ID: ${{secrets.TEST_FIREBASE_APP_ID}}
+ TEST_FIREBASE_RTDB_URI: ${{secrets.TEST_FIREBASE_RTDB_URI}}
+ TEST_FIREBASE_TENANT_ID: ${{secrets.TEST_FIREBASE_TENANT_ID}}
+ TEST_REGISTRATION_TOKENS: ${{secrets.TEST_REGISTRATION_TOKENS}}
+ FIREBASE_DATABASE_EMULATOR_HOST: localhost:9100
+ FIREBASE_AUTH_EMULATOR_HOST: localhost:9099
+ XDEBUG_MODE: coverage
+ run: firebase emulators:exec --only auth,database --project beste-firebase 'XDEBUG_MODE=coverage vendor/bin/phpunit --group=emulator --exclude-group grpc --coverage-clover=coverage.xml --log-junit=test-report.xml'
+
+ - name: Upload emulator test results to Codecov
+ if: ${{ !cancelled() }}
+ uses: codecov/codecov-action@v5
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+ flags: emulator
+ report_type: test_results
+ fail_ci_if_error: false
+
+ - name: Upload emulator coverage to Codecov
+ if: ${{ !cancelled() }}
+ uses: codecov/codecov-action@v5
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+ files: ./coverage.xml
+ flags: emulator
+ fail_ci_if_error: false
+
+ grpc-tests:
+ name: gRPC Tests (PHP 8.5)
+ needs:
+ - dependency-validation
+ runs-on: ubuntu-latest
+ timeout-minutes: 20
+ # Non-blocking while the gRPC extension is broken/unstable on PHP 8.5.
+ # See https://github.com/shivammathur/setup-php/issues/1041.
+ # Remove this once upstream releases a stable extension and tests pass.
+ continue-on-error: true
+
+ env:
+ key: cache-grpc
+ php-version: 8.5
+ extensions: grpc
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v6
+ with:
+ ref: ${{ github.event.workflow_run.head_sha || github.sha }}
+
+ - name: Setup cache environment
+ id: extcache
+ uses: shivammathur/cache-extensions@v1
+ with:
+ php-version: ${{ env.php-version }}
+ extensions: ${{ env.extensions }}
+ key: ${{ env.key }}
+
+ - name: Cache extensions
+ uses: actions/cache@v5.0.3
+ with:
+ path: ${{ steps.extcache.outputs.dir }}
+ key: ${{ steps.extcache.outputs.key }}
+ restore-keys: ${{ steps.extcache.outputs.key }}
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ env.php-version }}
+ extensions: ${{ env.extensions }}
+ ini-values: grpc.grpc_verbosity=error, grpc.grpc_trace=
+ tools: composer, pecl
+ coverage: xdebug
+
+ - name: Setup problem matchers for PHP
+ run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
+
+ - name: Verify gRPC extension
+ id: grpc
+ run: php -m | grep -i '^grpc$'
+
+ - name: Get Composer cache directory
+ id: composer-cache
+ if: ${{ steps.grpc.outcome == 'success' }}
+ shell: bash
+ run: |
+ echo "dir=$(composer config cache-files-dir)" >> "$GITHUB_OUTPUT"
+
+ - name: Cache Composer cache directory
+ if: ${{ steps.grpc.outcome == 'success' }}
+ uses: actions/cache@v5
+ with:
+ path: ${{ steps.composer-cache.outputs.dir }}
+ key: ${{ runner.os }}-composer-${{ hashFiles('composer.json', 'composer.lock') }}
+ restore-keys: ${{ runner.os }}-composer-
+
+ - name: Install dependencies with Composer
+ if: ${{ steps.grpc.outcome == 'success' }}
+ run: composer install --no-interaction --no-progress --ansi
+
+ - name: Setup Problem Matchers for PHPUnit
+ run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
+
+ - name: Run gRPC Tests
+ id: grpc-tests
+ if: ${{ steps.grpc.outcome == 'success' }}
+ env:
+ GOOGLE_APPLICATION_CREDENTIALS: ${{secrets.GOOGLE_APPLICATION_CREDENTIALS}}
+ TEST_FIREBASE_APP_ID: ${{secrets.TEST_FIREBASE_APP_ID}}
+ TEST_FIREBASE_RTDB_URI: ${{secrets.TEST_FIREBASE_RTDB_URI}}
+ TEST_FIREBASE_TENANT_ID: ${{secrets.TEST_FIREBASE_TENANT_ID}}
+ TEST_REGISTRATION_TOKENS: ${{secrets.TEST_REGISTRATION_TOKENS}}
+ XDEBUG_MODE: coverage
+ run: vendor/bin/phpunit --testsuite=integration --group grpc --coverage-clover=coverage.xml --log-junit=test-report.xml --testdox
+
+ - name: Upload gRPC test results to Codecov
+ if: ${{ !cancelled() && steps.grpc.outcome == 'success' }}
+ uses: codecov/codecov-action@v5
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+ flags: grpc
+ report_type: test_results
+ fail_ci_if_error: false
+
+ - name: Upload gRPC coverage to Codecov
+ if: ${{ !cancelled() && steps.grpc.outcome == 'success' }}
+ uses: codecov/codecov-action@v5
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+ files: ./coverage.xml
+ flags: grpc
+ fail_ci_if_error: false
+
+ - name: Summarize gRPC failures
+ if: ${{ always() && (steps.grpc.outcome == 'failure' || steps.grpc-tests.outcome == 'failure') }}
+ run: |
+ echo "::notice::gRPC tests are non-blocking due to missing/broken gRPC on PHP 8.5."
+ {
+ echo "### gRPC tests are non-blocking"
+ echo
+ echo "gRPC extension was not available or gRPC tests failed (likely due to missing/broken gRPC on PHP 8.5)."
+ echo "See https://github.com/shivammathur/setup-php/issues/1041."
+ } >> "$GITHUB_STEP_SUMMARY"
diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml
deleted file mode 100644
index 62680278..00000000
--- a/.github/workflows/static-analysis.yml
+++ /dev/null
@@ -1,60 +0,0 @@
-name: Static Analysis
-
-on:
- pull_request:
- paths:
- - 'src/**'
- - 'tests/**'
- - '.github/workflows/static-analysis.yml'
- - 'composer.json'
- - 'phpstan.neon.dist'
- push:
- branches: ['8.x']
- paths:
- - 'src/**'
- - 'tests/**'
- - '.github/workflows/static-analysis.yml'
- - 'composer.json'
- - 'phpstan.neon.dist'
- workflow_dispatch:
-
-permissions:
- contents: read
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
- cancel-in-progress: true
-
-jobs:
- phpstan:
- name: "PHPStan (PHP ${{ matrix.php }})"
- runs-on: ubuntu-latest
-
- strategy:
- fail-fast: false
- matrix:
- php:
- - "8.3"
- - "8.4"
- - "8.5"
-
- steps:
- - name: Checkout code
- uses: actions/checkout@v6
-
- - name: Setup PHP
- uses: shivammathur/setup-php@v2
- with:
- php-version: ${{ matrix.php }}
- tools: composer, pecl
- coverage: none
-
- - uses: "ramsey/composer-install@v3"
- with:
- composer-options: "--ignore-platform-req=ext-grpc"
-
- - name: Setup problem matchers for PHP
- run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
-
- - name: Run PHPStan
- run: XDEBUG_MODE=off vendor/bin/phpstan analyse --no-progress --error-format=github
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
deleted file mode 100644
index 25e1b464..00000000
--- a/.github/workflows/tests.yml
+++ /dev/null
@@ -1,85 +0,0 @@
-name: Tests
-
-on:
- pull_request:
- paths:
- - 'src/**'
- - 'tests/**'
- - '.github/workflows/tests.yml'
- - 'composer.json'
- - 'phpstan.neon.dist'
- push:
- branches: ['8.x']
- paths:
- - 'src/**'
- - 'tests/**'
- - '.github/workflows/tests.yml'
- - 'composer.json'
- - 'phpstan.neon.dist'
- workflow_dispatch:
-
-permissions:
- contents: read
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
- cancel-in-progress: true
-
-jobs:
- tests:
- name: "PHP ${{ matrix.php }}, ${{ matrix.dependencies }} deps"
- runs-on: ubuntu-latest
-
- strategy:
- fail-fast: false
- matrix:
- php:
- - "8.3"
- - "8.4"
- - "8.5"
- dependencies:
- - "lowest"
- - "highest"
-
- steps:
- - name: Checkout code
- uses: actions/checkout@v6
-
- - name: Setup PHP
- uses: shivammathur/setup-php@v2
- with:
- php-version: ${{ matrix.php }}
- tools: composer, pecl
- coverage: xdebug
-
- - uses: "ramsey/composer-install@v3"
- with:
- composer-options: "--ignore-platform-req=ext-grpc"
- dependency-versions: "${{ matrix.dependencies }}"
-
- - name: Setup problem matchers for PHP
- run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
-
- - name: Setup Problem Matchers for PHPUnit
- run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
-
- - name: Run PHPUnit
- run: vendor/bin/phpunit --testsuite=unit --coverage-clover=coverage.xml --log-junit=test-report.xml --testdox
-
- - name: Upload test results to Codecov
- if: ${{ !cancelled() }}
- uses: codecov/codecov-action@v5
- with:
- token: ${{ secrets.CODECOV_TOKEN }}
- flags: unit
- report_type: test_results
- fail_ci_if_error: false
-
- - name: Upload coverage to Codecov
- if: ${{ !cancelled() }}
- uses: codecov/codecov-action@v5
- with:
- token: ${{ secrets.CODECOV_TOKEN }}
- files: ./coverage.xml
- flags: unit
- fail_ci_if_error: false
diff --git a/README.md b/README.md
index 338fd16d..d29417ab 100644
--- a/README.md
+++ b/README.md
@@ -7,9 +7,9 @@
[](https://packagist.org/packages/kreait/firebase-php)
[](https://packagist.org/packages/kreait/firebase-php/stats)
[](https://packagist.org/packages/kreait/firebase-php/stats)
-[](https://github.com/beste/firebase-php/actions/workflows/tests.yml)
-[](https://github.com/beste/firebase-php/actions/workflows/integration-tests.yml)
-[](https://github.com/beste/firebase-php/actions/workflows/emulator-tests.yml)
+[](https://github.com/beste/firebase-php/actions/workflows/ci.yml)
+[](https://github.com/beste/firebase-php/actions/workflows/secure-tests.yml)
+[](https://github.com/beste/firebase-php/actions/workflows/docs.yml)
[](https://github.com/sponsors/jeromegamez)
diff --git a/docs/index.rst b/docs/index.rst
index 6a4155fa..d39c68f1 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -14,9 +14,9 @@ Firebase Admin SDK for PHP

-
-
-
+
+
+
From e8e7cfafc9c0bc554270dfc231990b6a0a146e7b Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 09:38:29 +0000
Subject: [PATCH 3/3] docs-deps(deps): bump sphinx from 7.2.6 to 9.1.0 in /docs
Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 7.2.6 to 9.1.0.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/master/CHANGES.rst)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v7.2.6...v9.1.0)
---
updated-dependencies:
- dependency-name: sphinx
dependency-version: 9.1.0
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot]
---
docs/pyproject.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/pyproject.toml b/docs/pyproject.toml
index f3635a18..03a40436 100644
--- a/docs/pyproject.toml
+++ b/docs/pyproject.toml
@@ -9,7 +9,7 @@ dependencies = [
"linkify-it-py>=2.0.3",
"matplotlib>=3.10.6",
"myst-parser>=4.0.1",
- "sphinx==7.2.6",
+ "sphinx==9.1.0",
"sphinx-autobuild>=2025.8.25",
"sphinx-copybutton>=0.5.2",
"sphinx-design>=0.6.1",