Compare commits

...

64 Commits

Author SHA1 Message Date
Joas Schilling
d49ed65265 fixup! I have no idea what I'm doing 2024-07-09 13:52:20 +02:00
Joas Schilling
61f3289a96 I have no idea what I'm doing
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-09 13:00:13 +02:00
Joas Schilling
cb8c68e25e reduce CI waste 2024-07-09 12:59:55 +02:00
Joas Schilling
2257ecb36b Try to workaround oracles primary key
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-09 11:59:07 +02:00
Joas Schilling
a20d9c85c9 fix(CI): Provide system account on installation
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-08 15:17:17 +02:00
Joas Schilling
7df4bb7b01 debug connection
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-05 12:24:50 +02:00
Joas Schilling
cce5822f81 fixup! fixup! Use new database name 2024-07-05 12:24:45 +02:00
Joas Schilling
a04c3b2bb0 fixup! Use new database name 2024-07-05 11:59:01 +02:00
Joas Schilling
04de2cb722 Use new database name
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-05 11:53:52 +02:00
Joas Schilling
15bd2d7125 Adjust ports
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-05 11:39:06 +02:00
Joas Schilling
d89343c183 fix(CI): Test against supported Oracle versions
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 15:10:12 +02:00
Joas Schilling
0b2357f7f8 Test oracle
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:41:15 +02:00
Joas Schilling
67002493d2 Remove CI 2024-07-04 14:37:55 +02:00
Joas Schilling
5fdc5d5011 fix(db)!: Too few arguments to function Doctrine\DBAL\Query\Expression\ExpressionBuilder::or(), 0 passed and atleast 1 expected
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:53 +02:00
Joas Schilling
8b7f8e14d6 fix(tests): Also handle the case where the schema is cached and the DELETE fails
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:52 +02:00
Joas Schilling
72c8c3af3a fix(tests): Adjust postgres schema diffing
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:52 +02:00
Joas Schilling
b2cf45cdaa fix(tests): Add length to test columns that bypass the migration service
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:50 +02:00
Joas Schilling
f0348be4c8 fix(db): Replace more Platform usages
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:50 +02:00
Joas Schilling
5718e8fff5 fix(tests): Fix changes in doctrine's Exception handling
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:49 +02:00
Joas Schilling
4c80fdd2bd fix(db): Adjust unit tests of query builder
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:49 +02:00
Joas Schilling
fc383a323f fix(tests): Adjust the migrator test
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:48 +02:00
Joas Schilling
8153c38efe fix(db): Don't set null as type
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:48 +02:00
Joas Schilling
de5a7c3c73 fix(db)!: Reimplement the query logger with a doctrine middleware
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:47 +02:00
Joas Schilling
1370693133 fix(db): Remove usage of Platforms
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:47 +02:00
Joas Schilling
6b2f1367cd fix(db): Map parameter types to doctrine's enums
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:46 +02:00
Joas Schilling
98b6c7c48a fix(db): Add a hint that we return PHP_INT_MAX
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:46 +02:00
Joas Schilling
66aac18bad fix(db)!: OCP\DB\IPreparedStatement::bindParam() is deprecated and calls bindValue() internally
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:45 +02:00
Joas Schilling
715656927c fix(db): Argument 2 of \Doctrine\DBAL\Platforms\AbstractPlatform::getBitAndComparisonExpression expects string
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:45 +02:00
Joas Schilling
bae31bfa7b fix(db): Method \Doctrine\DBAL\Platforms\AbstractPlatform::getIdentifierQuoteCharacter() does not exist
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:45 +02:00
Joas Schilling
926f2ab887 fix(db): Too many arguments for method \Doctrine\DBAL\Connection::quote() - saw 2
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:44 +02:00
Joas Schilling
60217aac39 fix(db): No longer return result of Connection::connect()
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:44 +02:00
Joas Schilling
df7d088653 fix(db)!: Deprecate getDatabasePlatform which leaks 3rdparty
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:43 +02:00
Joas Schilling
e8ef23d052 fix(db): Too few arguments for Doctrine\DBAL\Driver::getDatabasePlatform - expecting versionProvider to be passed
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:43 +02:00
Joas Schilling
5823d58d30 fix(db)!: Doctrine\DBAL\Platforms\MySQL80Platform requires the length of a VARCHAR column to be specified
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:43 +02:00
Joas Schilling
55a8f33873 fix(db): Doctrine Event Manager is removed
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:42 +02:00
Joas Schilling
2b83016a2b fix(db): TooManyArguments: Too many arguments for method Doctrine\DBAL\Statement::executeQuery()
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:42 +02:00
Joas Schilling
4bbaae5798 fix(db): ExpressionBuilder::like expects string, but OCP\DB\QueryBuilder\IQueryFunction provided
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:41 +02:00
Joas Schilling
6e90ddf41a fix(db): Doctrine\DBAL\Query\Expression\CompositeExpression::add* does not exist
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:40 +02:00
Joas Schilling
ec1a3d6cd3 fix(db): Doctrine\DBAL\Query\QueryBuilder::getState does not exist
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:39 +02:00
Joas Schilling
4c1003122d fix(db): Doctrine\DBAL\Schema\Schema::getTableNames() was removed
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:38 +02:00
Joas Schilling
165443046a fix(db): Interface Doctrine\DBAL\Exception cannot be instantiated
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:37 +02:00
Joas Schilling
c6cd20ea8a fix(db)!: Doctrine\DBAL\FetchMode was removed
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:37 +02:00
Joas Schilling
f6ac69a2a0 fix(db)!: Doctrine\DBAL\Platforms\PostgreSQL94Platform was removed
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:36 +02:00
Joas Schilling
d9e69e14f3 fix(db)!: Table alias for DELETE and UPDATE no longer supported
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:36 +02:00
Joas Schilling
2d27a32870 fix(db): InaccessibleMethod: Cannot access private method Doctrine\DBAL\Statement::execute from context OC\DB\PreparedStatement
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:36 +02:00
Joas Schilling
fb3d4d579f fix(db): Don't use removed/deprecated methods in setup
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:35 +02:00
Joas Schilling
c0d2f7ee21 fix(CI): Operand of type Doctrine\DBAL\Schema\Column is always truthy
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:35 +02:00
Joas Schilling
a20110bdc4 fix(db): UndefinedConstant: Constant Doctrine\DBAL\Connection::PARAM_STR_ARRAY is not defined
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:34 +02:00
Joas Schilling
72151b550c fix(db): Table::getPrimaryKeyColumns() was removed
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:34 +02:00
Joas Schilling
f45ac5bb68 fix(db): Doctrine\DBAL\Query\Expression\ExpressionBuilder::andX() and ::orX() were removed
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:34 +02:00
Joas Schilling
3c5acbcb1a fix(db): Doctrine\DBAL\Connection::executeUpdate() was removed
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:33 +02:00
Joas Schilling
287d5271e0 fix(db)!: Doctrine\DBAL\Connection::getSchemaManager was removed, use Connection::createSchemaManager instead
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:33 +02:00
Joas Schilling
466f455e93 fix(db)!: Doctrine\DBAL\Schema\Table::hasPrimaryKey() was removed, use Table::getPrimaryKey` instead.
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:32 +02:00
Joas Schilling
27c49e7a9a fix(db)!: Table::changeColumn() was renamed to Table::modifyColumn()
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:32 +02:00
Joas Schilling
f6f53a8ca8 fix(db)!: Doctrine\DBAL\Types\Type::getName() was removed
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:31 +02:00
Joas Schilling
e6e1bd8b93 fix(db): Fix internal calls to doctrine's fetch functions
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:31 +02:00
Joas Schilling
648b20c588 fix(db)!: Manually track the query type and whether WHERE is empty
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:30 +02:00
Joas Schilling
76ef7dd71e fix(db): Remove usage of dropped doctrine event manager
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:30 +02:00
Joas Schilling
6d0e8e4606 fix(db): Use new function name to get the schema
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:29 +02:00
Joas Schilling
72886c0bfb fix(db): Make sure setComment() is only called with strings
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:29 +02:00
Joas Schilling
de0141d83c fix(db)!: Empty and adjust query-part related methods
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:29 +02:00
Joas Schilling
a5432e3c69 fix(db): Adjust Connection signature to updated doctrine one
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:28 +02:00
Joas Schilling
015a3e85fe fix(db)!: Fix casing of doctrine's SQLitePlatform
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:28 +02:00
Joas Schilling
c2394958c0 chore(deps): Bump doctrine/dbal from 3.8.3 to 4.0.4
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-07-04 14:19:27 +02:00
127 changed files with 1230 additions and 5571 deletions

View File

@@ -1,98 +0,0 @@
# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Code checkers
on:
pull_request:
permissions:
contents: read
concurrency:
group: autocheckers-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src }}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '3rdparty/**'
- '**/appinfo/**'
- '**/lib/**'
- '**/templates/**'
- 'vendor/**'
- 'vendor-bin/**'
- 'composer.json'
- 'composer.lock'
- '**.php'
autocheckers:
runs-on: ubuntu-latest
needs: changes
if: needs.changes.outputs.src != 'false'
strategy:
matrix:
php-versions: ['8.3']
name: PHP checkers
steps:
- name: Checkout server
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: ${{ matrix.php-versions }}
extensions: ctype, json, mbstring
coverage: none
ini-file: development
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up dependencies
run: composer i
- name: Check auto loaders
run: bash ./build/autoloaderchecker.sh
- name: Check translations are JSON decodeable
run: php ./build/translation-checker.php
- name: Check translations do not contain triple dot but ellipsis
run: php ./build/triple-dot-checker.php
- name: Check .htaccess does not contain invalid changes
run: php ./build/htaccess-checker.php
- name: Check that all and only expected files are included
run: php ./build/files-checker.php
summary:
permissions:
contents: none
runs-on: ubuntu-latest-low
needs: [changes, autocheckers]
if: always()
name: autocheckers-summary
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.autocheckers.result != 'success' }}; then exit 1; fi

View File

@@ -1,40 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Block merges for EOL
on: pull_request
permissions:
contents: read
concurrency:
group: block-merge-eol-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
block-merges-eol:
name: Block merges for EOL branches
# Only run on stableXX branches
if: startsWith( github.base_ref, 'stable')
runs-on: ubuntu-latest-low
steps:
- name: Set server major version environment
run: |
# retrieve version number from branch reference
server_major=$(echo "${{ github.base_ref }}" | sed -En 's/stable//p')
echo "server_major=$server_major" >> $GITHUB_ENV
echo "current_month=$(date +%Y-%m)" >> $GITHUB_ENV
- name: Checking if ${{ env.server_major }} is EOL
run: |
curl -s https://raw.githubusercontent.com/nextcloud-releases/updater_server/production/config/major_versions.json \
| jq '.["${{ env.server_major }}"]["eol"] // "9999-99" | . >= "${{ env.current_month }}"' \
| grep -q true

View File

@@ -1,35 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Block merges during freezes
on:
pull_request:
types: [opened, ready_for_review, reopened, synchronize]
permissions:
contents: read
concurrency:
group: block-merge-freeze-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
block-merges-during-freeze:
name: Block merges during freezes
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest-low
steps:
- name: Download version.php from ${{ github.base_ref }}
run: curl 'https://raw.githubusercontent.com/nextcloud/server/${{ github.base_ref }}/version.php' --output version.php
- name: Run check
run: cat version.php | grep 'OC_VersionString' | grep -i -v 'RC'

View File

@@ -1,55 +0,0 @@
# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Block merging with outdated 3rdparty/
on:
pull_request:
types: [opened, ready_for_review, reopened, synchronize]
permissions:
contents: read
concurrency:
group: block-outdated-3rdparty-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
block-outdated-3rdparty:
name: Block merging with outdated 3rdparty/
runs-on: ubuntu-latest-low
steps:
- name: Check requirement
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '3rdparty'
- 'version.php'
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: 3rdparty commit hash on current branch
id: actual
run: |
echo "commit=$(git submodule status | grep ' 3rdparty' | egrep -o '[a-f0-9]{40}')" >> "$GITHUB_OUTPUT"
- name: Last 3rdparty commit on target branch
id: target
run: |
echo "commit=$(git ls-remote https://github.com/nextcloud/3rdparty refs/heads/${{ github.base_ref }} | awk '{ print $1}')" >> "$GITHUB_OUTPUT"
- name: Compare if 3rdparty commits are different
run: |
echo '3rdparty/ seems to not point to the last commit of the dedicated branch:'
echo 'Branch has: ${{ steps.actual.outputs.commit }}'
echo '${{ github.base_ref }} has: ${{ steps.target.outputs.commit }}'
- name: Fail if 3rdparty commits are different
if: ${{ steps.changes.outputs.src != 'false' && steps.actual.outputs.commit != steps.target.outputs.commit }}
run: |
exit 1

View File

@@ -1,34 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Block unconventional commits
on:
pull_request:
types: [opened, ready_for_review, reopened, synchronize]
permissions:
contents: read
concurrency:
group: block-unconventional-commits-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
block-unconventional-commits:
name: Block unconventional commits
runs-on: ubuntu-latest-low
steps:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: webiny/action-conventional-commits@8bc41ff4e7d423d56fa4905f6ff79209a78776c7 # v1.3.0
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,148 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Compile Command
on:
issue_comment:
types: [created]
jobs:
init:
runs-on: ubuntu-latest
# On pull requests and if the comment starts with `/compile`
if: github.event.issue.pull_request != '' && startsWith(github.event.comment.body, '/compile')
outputs:
git_path: ${{ steps.git-path.outputs.path }}
arg1: ${{ steps.command.outputs.arg1 }}
arg2: ${{ steps.command.outputs.arg2 }}
head_ref: ${{ steps.comment-branch.outputs.head_ref }}
base_ref: ${{ steps.comment-branch.outputs.base_ref }}
steps:
- name: Check actor permission
uses: skjnldsv/check-actor-permission@69e92a3c4711150929bca9fcf34448c5bf5526e7 # v2
with:
require: write
- name: Add reaction on start
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
repository: ${{ github.event.repository.full_name }}
comment-id: ${{ github.event.comment.id }}
reactions: '+1'
- name: Parse command
uses: skjnldsv/parse-command-comment@5c955203c52424151e6d0e58fb9de8a9f6a605a1 # v2
id: command
# Init path depending on which command is run
- name: Init path
id: git-path
run: |
if ${{ startsWith(steps.command.outputs.arg1, '/') }}; then
echo "path=${{steps.command.outputs.arg1}}" >> $GITHUB_OUTPUT
else
echo "path=${{steps.command.outputs.arg2}}" >> $GITHUB_OUTPUT
fi
- name: Init branch
uses: xt0rted/pull-request-comment-branch@d97294d304604fa98a2600a6e2f916a84b596dc7 # v1
id: comment-branch
process:
runs-on: ubuntu-latest
needs: init
steps:
- name: Restore cached git repository
uses: buildjet/cache@e376f15c6ec6dc595375c78633174c7e5f92dc0e # v3
with:
path: .git
key: git-repo
- name: Checkout ${{ needs.init.outputs.head_ref }}
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
fetch-depth: 0
ref: ${{ needs.init.outputs.head_ref }}
- name: Setup git
run: |
git config --local user.email 'nextcloud-command@users.noreply.github.com'
git config --local user.name 'nextcloud-command'
- name: Read package.json node and npm engines version
uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3
id: package-engines-versions
with:
fallbackNode: '^20'
fallbackNpm: '^10'
- name: Set up node ${{ steps.package-engines-versions.outputs.nodeVersion }}
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v3
with:
node-version: ${{ steps.package-engines-versions.outputs.nodeVersion }}
cache: npm
- name: Set up npm ${{ steps.package-engines-versions.outputs.npmVersion }}
run: npm i -g 'npm@${{ steps.package-engines-versions.outputs.npmVersion }}'
- name: Rebase to ${{ needs.init.outputs.base_ref }}
if: ${{ contains(needs.init.outputs.arg1, 'rebase') }}
run: |
git fetch origin '${{ needs.init.outputs.base_ref }}:${{ needs.init.outputs.base_ref }}'
git rebase 'origin/${{ needs.init.outputs.base_ref }}'
- name: Install dependencies & build
env:
CYPRESS_INSTALL_BINARY: 0
PUPPETEER_SKIP_DOWNLOAD: true
run: |
npm ci
npm run build --if-present
- name: Commit default
if: ${{ !contains(needs.init.outputs.arg1, 'fixup') && !contains(needs.init.outputs.arg1, 'amend') }}
run: |
git add '${{ github.workspace }}${{ needs.init.outputs.git_path }}'
git commit --signoff -m 'chore(assets): Recompile assets'
- name: Commit fixup
if: ${{ contains(needs.init.outputs.arg1, 'fixup') }}
run: |
git add '${{ github.workspace }}${{ needs.init.outputs.git_path }}'
git commit --fixup=HEAD --signoff
- name: Commit amend
if: ${{ contains(needs.init.outputs.arg1, 'amend') }}
run: |
git add '${{ github.workspace }}${{ needs.init.outputs.git_path }}'
git commit --amend --no-edit --signoff
# Remove any [skip ci] from the amended commit
git commit --amend -m "$(git log -1 --format='%B' | sed '/\[skip ci\]/d')"
- name: Push normally
if: ${{ !contains(needs.init.outputs.arg1, 'rebase') && !contains(needs.init.outputs.arg1, 'amend') }}
run: git push origin '${{ needs.init.outputs.head_ref }}'
- name: Force push
if: ${{ contains(needs.init.outputs.arg1, 'rebase') || contains(needs.init.outputs.arg1, 'amend') }}
run: git push --force origin '${{ needs.init.outputs.head_ref }}'
- name: Add reaction on failure
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0
if: failure()
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
repository: ${{ github.event.repository.full_name }}
comment-id: ${{ github.event.comment.id }}
reactions: "-1"

View File

@@ -1,62 +0,0 @@
# SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Update 3rdparty command
on:
issue_comment:
types: created
permissions:
contents: read
jobs:
rebase:
runs-on: ubuntu-latest
permissions:
contents: none
# On pull requests and if the comment starts with `/update-3rdparty`
if: github.event.issue.pull_request != '' && startsWith(github.event.comment.body, '/update-3rdparty')
steps:
- name: Add reaction on start
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v3.0.1
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
repository: ${{ github.event.repository.full_name }}
comment-id: ${{ github.event.comment.id }}
reactions: '+1'
- name: Init branch
uses: xt0rted/pull-request-comment-branch@d97294d304604fa98a2600a6e2f916a84b596dc7 # v1
id: comment-branch
- name: Checkout ${{ steps.comment-branch.outputs.head_ref }}
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
fetch-depth: 0
token: ${{ secrets.COMMAND_BOT_PAT }}
ref: ${{ steps.comment-branch.outputs.head_ref }}
- name: Setup git
run: |
git config --local user.email 'nextcloud-command@users.noreply.github.com'
git config --local user.name 'nextcloud-command'
- name: Pull 3rdparty
run: git submodule foreach 'if [ "$sm_path" == "3rdparty" ]; then git pull origin '"'"'${{ github.event.issue.pull_request.base.ref }}'"'"'; fi'
- name: Commit and push changes
run: |
git add 3rdparty
git commit -s -m 'Update submodule 3rdparty to latest ${{ github.event.issue.pull_request.base.ref }}'
git push
- name: Add reaction on failure
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v3.0.1
if: failure()
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
repository: ${{ github.event.repository.full_name }}
comment-id: ${{ github.event.comment.id }}
reactions: '-1'

View File

@@ -1,171 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Cypress
on: pull_request
concurrency:
group: cypress-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
env:
# Adjust APP_NAME if your repository name is different
APP_NAME: ${{ github.event.repository.name }}
# Server requires head_ref instead of base_ref, as we want to test the PR branch
BRANCH: ${{ github.head_ref || github.ref_name }}
jobs:
init:
runs-on: ubuntu-latest
outputs:
nodeVersion: ${{ steps.versions.outputs.nodeVersion }}
npmVersion: ${{ steps.versions.outputs.npmVersion }}
env:
PUPPETEER_SKIP_DOWNLOAD: true
steps:
- name: Checkout server
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
# We need to checkout submodules for 3rdparty
submodules: true
- name: Check composer.json
id: check_composer
uses: andstor/file-existence-action@076e0072799f4942c8bc574a82233e1e4d13e9d6 # v3.0.0
with:
files: "composer.json"
- name: Install composer dependencies
if: steps.check_composer.outputs.files_exists == 'true'
run: composer install --no-dev
- name: Read package.json node and npm engines version
uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3
id: versions
with:
fallbackNode: "^20"
fallbackNpm: "^10"
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
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 node dependencies & build app
run: |
npm ci
TESTING=true npm run build --if-present
- name: Show cypress version
run: npm run cypress:version
- name: Save context
uses: buildjet/cache/save@e376f15c6ec6dc595375c78633174c7e5f92dc0e # v3
with:
key: cypress-context-${{ github.run_id }}
path: ./
cypress:
runs-on: ubuntu-latest
needs: init
strategy:
fail-fast: false
matrix:
# Run multiple copies of the current job in parallel
# Please increase the number or runners as your tests suite grows (0 based index for e2e tests)
containers: ["component", '0', '1', '2', '3', '4', '5']
# Hack as strategy.job-total includes the component and GitHub does not allow math expressions
# Always align this number with the total of e2e runners (max. index + 1)
total-containers: [6]
name: runner ${{ matrix.containers }}
steps:
- name: Restore context
uses: buildjet/cache/restore@e376f15c6ec6dc595375c78633174c7e5f92dc0e # v3
with:
fail-on-cache-miss: true
key: cypress-context-${{ github.run_id }}
path: ./
- name: Set up node ${{ needs.init.outputs.nodeVersion }}
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: ${{ needs.init.outputs.nodeVersion }}
- name: Set up npm ${{ needs.init.outputs.npmVersion }}
run: npm i -g 'npm@${{ needs.init.outputs.npmVersion }}'
- name: Run ${{ matrix.containers == 'component' && 'component' || 'E2E' }} cypress tests
uses: cypress-io/github-action@8d3918616d8ac34caa2b49afc8b408b6a872a6f5 # v6.7.1
with:
component: ${{ matrix.containers == 'component' }}
group: ${{ matrix.use-cypress-cloud && matrix.containers == 'component' && 'Run component' || matrix.use-cypress-cloud && 'Run E2E' || '' }}
# cypress env
ci-build-id: ${{ matrix.use-cypress-cloud && format('{0}-{1}', github.sha, github.run_number) || '' }}
tag: ${{ matrix.use-cypress-cloud && github.event_name || '' }}
env:
# Needs to be prefixed with CYPRESS_
CYPRESS_BRANCH: ${{ env.BRANCH }}
# https://github.com/cypress-io/github-action/issues/124
COMMIT_INFO_MESSAGE: ${{ github.event.pull_request.title }}
# Needed for some specific code workarounds
TESTING: true
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
SPLIT: ${{ matrix.total-containers }}
SPLIT_INDEX: ${{ matrix.containers == 'component' && 0 || matrix.containers }}
- name: Upload snapshots
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
if: always()
with:
name: snapshots_${{ matrix.containers }}
path: cypress/snapshots
- name: Extract NC logs
if: failure() && matrix.containers != 'component'
run: docker logs nextcloud-cypress-tests-${{ env.APP_NAME }} > nextcloud.log
- name: Upload NC logs
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
if: failure() && matrix.containers != 'component'
with:
name: nc_logs_${{ matrix.containers }}
path: nextcloud.log
- name: Create data dir archive
if: failure() && matrix.containers != 'component'
run: docker exec nextcloud-cypress-tests-server tar -cvjf - data > data.tar
- name: Upload data dir archive
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
if: failure() && matrix.containers != 'component'
with:
name: nc_data_${{ matrix.containers }}
path: data.tar
summary:
runs-on: ubuntu-latest-low
needs: [init, cypress]
if: always()
name: cypress-summary
steps:
- name: Summary status
run: if ${{ needs.init.result != 'success' || ( needs.cypress.result != 'success' && needs.cypress.result != 'skipped' ) }}; then exit 1; fi

View File

@@ -1,43 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Dependabot
on:
pull_request_target:
branches:
- main
- master
- stable*
permissions:
contents: read
concurrency:
group: dependabot-approve-merge-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
auto-approve-merge:
if: github.actor == 'dependabot[bot]' || github.actor == 'renovate[bot]'
runs-on: ubuntu-latest-low
permissions:
# for hmarr/auto-approve-action to approve PRs
pull-requests: write
steps:
# GitHub actions bot approve
- uses: hmarr/auto-approve-action@b40d6c9ed2fa10c9a2749eca7eb004418a705501 # v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
# Nextcloud bot approve and merge request
- uses: ahmadnassri/action-dependabot-auto-merge@45fc124d949b19b6b8bf6645b6c9d55f4f9ac61a # v2
with:
target: minor
github-token: ${{ secrets.DEPENDABOT_AUTOMERGE_TOKEN }}

View File

@@ -1,121 +0,0 @@
# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: PHPUnit files_external FTP
on:
pull_request:
schedule:
- cron: "5 2 * * *"
concurrency:
group: files-external-ftp-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '3rdparty/**'
- 'apps/files_external/**'
- 'vendor/**'
- 'vendor-bin/**'
- 'composer.json'
- 'composer.lock'
- '**.php'
files-external-ftp:
runs-on: ubuntu-latest
needs: changes
if: ${{ github.repository_owner != 'nextcloud-gmbh' && needs.changes.outputs.src != 'false' }}
strategy:
# do not stop on another job's failure
fail-fast: false
matrix:
php-versions: ['8.1', '8.3']
ftpd: ['proftpd', 'vsftpd', 'pure-ftpd']
include:
- php-versions: '8.1'
coverage: ${{ github.event_name != 'pull_request' }}
name: php${{ matrix.php-versions }}-${{ matrix.ftpd }}
steps:
- name: Checkout server
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
submodules: true
- name: Set up ftpd
run: |
sudo mkdir /tmp/ftp
sudo chmod -R 0777 /tmp/ftp
if [[ "${{ matrix.ftpd }}" == 'proftpd' ]]; then echo '$6$Q7V2n3q2GRVv5YeQ$/AhLu07H76Asojy7bxGXMY1caKLAbp5Vt82LOZYMkD/8uDzyMAEXwk0c1Bdz1DkBsk2Vh/9SF130mOPavRGMo.' > /tmp/secret.txt; fi
if [[ "${{ matrix.ftpd }}" == 'proftpd' ]]; then echo 'FTP_ROOT=/home/test' > $GITHUB_ENV; fi
if [[ "${{ matrix.ftpd }}" == 'proftpd' ]]; then docker run --name ftp -d --net host -e PASV_ADDRESS=127.0.0.1 -e FTPUSER_NAME=test -v /tmp/secret.txt:/run/secrets/ftp-user-password-secret -v /tmp/ftp:/home/test instantlinux/proftpd; fi
if [[ "${{ matrix.ftpd }}" == 'vsftpd' ]]; then docker run --name ftp -d --net host -e FTP_USER=test -e FTP_PASS=test -e PASV_ADDRESS=127.0.0.1 -v /tmp/ftp:/home/vsftpd/test fauria/vsftpd; fi
if [[ "${{ matrix.ftpd }}" == 'pure-ftpd' ]]; then docker run --name ftp -d --net host -e "PUBLICHOST=localhost" -e FTP_USER_NAME=test -e FTP_USER_PASS=test -e FTP_USER_HOME=/home/test -v /tmp/ftp:/home/test -v /tmp/ftp:/etc/pure-ftpd/passwd stilliard/pure-ftpd; fi
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: ${{ matrix.php-versions }}
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
extensions: ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, redis, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
coverage: ${{ matrix.coverage && 'xdebug' || 'none' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Nextcloud
run: |
composer install
mkdir data
./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-host=127.0.0.1 --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password
./occ app:enable --force files_external
echo "<?php return ['run' => true,'host' => 'localhost','user' => 'test','password' => 'test', 'root' => '${{ env.FTP_ROOT }}'];" > apps/files_external/tests/config.ftp.php
- name: smoketest ftp
run: |
php -r 'var_dump(file_put_contents("ftp://test:test@localhost${{ env.FTP_ROOT }}/ftp.txt", "asd"));'
php -r 'var_dump(file_get_contents("ftp://test:test@localhost${{ env.FTP_ROOT }}/ftp.txt"));'
php -r 'var_dump(mkdir("ftp://test:test@localhost${{ env.FTP_ROOT }}/asdads"));'
ls -l /tmp/ftp
[ -f /tmp/ftp/ftp.txt ]
- name: PHPUnit
run: composer run test:files_external -- \
apps/files_external/tests/Storage/FtpTest.php \
${{ matrix.coverage && ' --coverage-clover ./clover.xml' || '' }}
- name: Upload code coverage
if: ${{ !cancelled() && matrix.coverage }}
uses: codecov/codecov-action@v4.1.1
with:
files: ./clover.xml
flags: phpunit-files-external-ftp
- name: ftpd logs
if: always()
run: |
docker logs ftp
ftp-summary:
runs-on: ubuntu-latest-low
needs: [changes, files-external-ftp]
if: always()
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.files-external-ftp.result != 'success' }}; then exit 1; fi

View File

@@ -1,187 +0,0 @@
# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: PHPUnit files_external S3
on:
pull_request:
schedule:
- cron: "5 2 * * *"
concurrency:
group: files-external-s3-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '3rdparty/**'
- 'apps/files_external/**'
- 'vendor/**'
- 'vendor-bin/**'
- 'composer.json'
- 'composer.lock'
- '**.php'
files-external-s3-minio:
runs-on: ubuntu-latest
needs: changes
if: ${{ github.repository_owner != 'nextcloud-gmbh' && needs.changes.outputs.src != 'false' }}
strategy:
matrix:
php-versions: ['8.1', '8.2', '8.3']
include:
- php-versions: '8.2'
coverage: ${{ github.event_name != 'pull_request' }}
name: php${{ matrix.php-versions }}-s3
services:
minio:
image: bitnami/minio
env:
MINIO_ROOT_USER: nextcloud
MINIO_ROOT_PASSWORD: bWluaW8tc2VjcmV0LWtleS1uZXh0Y2xvdWQ=
MINIO_DEFAULT_BUCKETS: nextcloud
ports:
- '9000:9000'
steps:
- name: Checkout server
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: ${{ matrix.php-versions }}
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, redis, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
coverage: ${{ matrix.coverage && 'xdebug' || 'none' }}
ini-file: development
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Nextcloud
env:
OBJECT_STORE_KEY: nextcloud
OBJECT_STORE_SECRET: bWluaW8tc2VjcmV0LWtleS1uZXh0Y2xvdWQ=
run: |
composer install
./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-host=127.0.0.1 --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password
./occ app:enable --force files_external
echo "<?php return ['run' => true, 'secret' => 'actually-not-secret', 'passwordsalt' => 'actually-not-secret', 'hostname' => 'localhost','key' => '$OBJECT_STORE_KEY','secret' => '$OBJECT_STORE_SECRET', 'bucket' => 'bucket', 'port' => 9000, 'use_ssl' => false, 'autocreate' => true, 'use_path_style' => true];" > apps/files_external/tests/config.amazons3.php
- name: Wait for S3
run: |
sleep 10
curl -f -m 1 --retry-connrefused --retry 10 --retry-delay 10 http://localhost:9000/minio/health/ready
- name: PHPUnit
run: composer run test:files_external -- \
apps/files_external/tests/Storage/Amazons3Test.php \
apps/files_external/tests/Storage/VersionedAmazonS3Test.php \
${{ matrix.coverage && ' --coverage-clover ./clover.xml' || '' }}
- name: Upload code coverage
if: ${{ !cancelled() && matrix.coverage }}
uses: codecov/codecov-action@v4.1.1
with:
files: ./clover.xml
flags: phpunit-files-external-s3
- name: S3 logs
if: always()
run: |
docker ps -a
docker ps -aq | while read container ; do IMAGE=$(docker inspect --format='{{.Config.Image}}' $container); echo $IMAGE; docker logs $container; echo "\n\n" ; done
files-external-s3-localstack:
runs-on: ubuntu-latest
needs: changes
if: ${{ github.repository_owner != 'nextcloud-gmbh' && needs.changes.outputs.src != 'false' }}
strategy:
matrix:
php-versions: ['8.1', '8.2', '8.3']
include:
- php-versions: '8.3'
coverage: true
name: php${{ matrix.php-versions }}-s3
services:
localstack:
env:
SERVICES: s3
DEBUG: 1
image: localstack/localstack
ports:
- "4566:4566"
steps:
- name: Checkout server
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: ${{ matrix.php-versions }}
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, redis, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
coverage: ${{ matrix.coverage && 'xdebug' || 'none' }}
ini-file: development
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Nextcloud
run: |
composer install
./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-host=127.0.0.1 --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password
./occ app:enable --force files_external
echo "<?php return ['run' => true,'hostname' => 'localhost','key' => 'ignored','secret' => 'ignored', 'bucket' => 'bucket', 'port' => 4566, 'use_ssl' => false, 'autocreate' => true, 'use_path_style' => true];" > apps/files_external/tests/config.amazons3.php
- name: PHPUnit
run: composer run test:files_external -- \
apps/files_external/tests/Storage/Amazons3Test.php \
apps/files_external/tests/Storage/VersionedAmazonS3Test.php \
${{ matrix.coverage && ' --coverage-clover ./clover.xml' || '' }}
- name: Upload code coverage
if: ${{ !cancelled() && matrix.coverage }}
uses: codecov/codecov-action@v4.1.1
with:
files: ./clover.xml
flags: phpunit-files-external-s3
- name: S3 logs
if: always()
run: |
docker ps -a
docker ps -aq | while read container ; do IMAGE=$(docker inspect --format='{{.Config.Image}}' $container); echo $IMAGE; docker logs $container; echo "\n\n" ; done
s3-external-summary:
runs-on: ubuntu-latest-low
needs: [changes, files-external-s3-minio, files-external-s3-localstack]
if: always()
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.files-external-s3-minio.result != 'success' && needs.files-external-s3-localstack.result != 'success' }}; then exit 1; fi

View File

@@ -1,111 +0,0 @@
# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: PHPUnit files_external sFTP
on:
pull_request:
schedule:
- cron: "5 2 * * *"
concurrency:
group: files-external-sftp-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '3rdparty/**'
- 'apps/files_external/**'
- 'vendor/**'
- 'vendor-bin/**'
- 'composer.json'
- 'composer.lock'
- '**.php'
files-external-sftp:
runs-on: ubuntu-latest
needs: changes
if: ${{ github.repository_owner != 'nextcloud-gmbh' && needs.changes.outputs.src != 'false' }}
strategy:
# do not stop on another job's failure
fail-fast: false
matrix:
php-versions: ['8.1', '8.3']
sftpd: ['openssh']
include:
- php-versions: '8.1'
coverage: ${{ github.event_name != 'pull_request' }}
name: php${{ matrix.php-versions }}-${{ matrix.sftpd }}
steps:
- name: Checkout server
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
submodules: true
- name: Set up sftpd
run: |
sudo mkdir /tmp/sftp
sudo chown -R 0777 /tmp/sftp
if [[ '${{ matrix.sftpd }}' == 'openssh' ]]; then docker run -p 2222:22 --name sftp -d -v /tmp/sftp:/home/test atmoz/sftp 'test:test:::data'; fi
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: ${{ matrix.php-versions }}
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
extensions: ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, redis, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
coverage: ${{ matrix.coverage && 'xdebug' || 'none' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Nextcloud
run: |
composer install
mkdir data
./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-host=127.0.0.1 --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password
./occ app:enable --force files_external
echo "<?php return ['run' => true, 'host' => 'localhost:2222','user' => 'test','password' => 'test', 'root' => 'data'];" > apps/files_external/tests/config.sftp.php
- name: PHPUnit
run: composer run test:files_external -- \
apps/files_external/tests/Storage/SftpTest.php \
apps/files_external/tests/Storage/SFTP_KeyTest.php \
${{ matrix.coverage && ' --coverage-clover ./clover.xml' || '' }}
- name: Upload code coverage
if: ${{ !cancelled() && matrix.coverage }}
uses: codecov/codecov-action@v4.1.1
with:
files: ./clover.xml
flags: phpunit-files-external-sftp
- name: sftpd logs
if: always()
run: |
ls -l /tmp/sftp
docker logs sftp
sftp-summary:
runs-on: ubuntu-latest-low
needs: [changes, files-external-sftp]
if: always()
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.files-external-sftp.result != 'success' }}; then exit 1; fi

View File

@@ -1,95 +0,0 @@
# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Samba Kerberos SSO
on:
pull_request:
schedule:
- cron: "5 2 * * *"
concurrency:
group: files-external-smb-kerberos-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '3rdparty/**'
- 'apps/files_external/**'
- 'vendor/**'
- 'vendor-bin/**'
- 'composer.json'
- 'composer.lock'
- '**.php'
files-external-smb-kerberos:
runs-on: ubuntu-22.04
needs: changes
if: ${{ github.repository_owner != 'nextcloud-gmbh' && needs.changes.outputs.src != 'false' }}
name: smb-kerberos-sso
steps:
- name: Checkout server
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
submodules: true
- name: Checkout user_saml
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
repository: nextcloud/user_saml
path: apps/user_saml
- name: Pull images
run: |
docker pull ghcr.io/icewind1991/samba-krb-test-dc
docker pull ghcr.io/icewind1991/samba-krb-test-apache
docker pull ghcr.io/icewind1991/samba-krb-test-client
docker tag ghcr.io/icewind1991/samba-krb-test-dc icewind1991/samba-krb-test-dc
docker tag ghcr.io/icewind1991/samba-krb-test-apache icewind1991/samba-krb-test-apache
docker tag ghcr.io/icewind1991/samba-krb-test-client icewind1991/samba-krb-test-client
- name: Setup AD-DC
run: |
DC_IP=$(apps/files_external/tests/sso-setup/start-dc.sh)
sleep 1
apps/files_external/tests/sso-setup/start-apache.sh $DC_IP $PWD
echo "DC_IP=$DC_IP" >> $GITHUB_ENV
- name: Set up Nextcloud
run: |
apps/files_external/tests/sso-setup/setup-sso-nc.sh
- name: Test SSO
run: |
apps/files_external/tests/sso-setup/test-sso-smb.sh ${{ env.DC_IP }}
- name: Show logs
if: always()
run: |
FILEPATH=$(docker exec --user 33 apache ./occ log:file | grep "Log file:" | cut -d' ' -f3)
echo "$FILEPATH:"
docker exec --user 33 apache cat $FILEPATH
sftp-summary:
runs-on: ubuntu-latest-low
needs: [changes, files-external-smb-kerberos]
if: always()
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.files-external-smb-kerberos.result != 'success' }}; then exit 1; fi

View File

@@ -1,110 +0,0 @@
# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: PHPUnit files_external SMB
on:
pull_request:
schedule:
- cron: "5 2 * * *"
concurrency:
group: files-external-smb-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '3rdparty/**'
- 'apps/files_external/**'
- 'vendor/**'
- 'vendor-bin/**'
- 'composer.json'
- 'composer.lock'
- '**.php'
files-external-smb:
runs-on: ubuntu-latest
needs: changes
if: ${{ github.repository_owner != 'nextcloud-gmbh' && needs.changes.outputs.src != 'false' }}
strategy:
matrix:
php-versions: ['8.1', '8.3']
include:
- php-versions: '8.1'
coverage: ${{ github.event_name != 'pull_request' }}
name: php${{ matrix.php-versions }}-smb
services:
samba:
image: ghcr.io/nextcloud/continuous-integration-samba:latest
ports:
- 445:445
steps:
- name: Checkout server
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: ${{ matrix.php-versions }}
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
extensions: ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, redis, session, simplexml, xmlreader, xmlwriter, zip, zlib, smbclient, sqlite, pdo_sqlite
coverage: ${{ matrix.coverage && 'xdebug' || 'none' }}
ini-file: development
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up smbclient
# This is needed as icewind/smb php library for notify
run: sudo apt-get install -y smbclient
- name: Set up Nextcloud
run: |
composer install
./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-host=127.0.0.1 --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password
./occ config:system:set --value true --type boolean allow_local_remote_servers
./occ app:enable --force files_external
echo "<?php return ['run'=>true, 'host'=>'localhost', 'user'=>'test', 'password'=>'test', 'root'=>'', 'share'=>'public'];" > apps/files_external/tests/config.smb.php
- name: Wait for smb
run: |
apps/files_external/tests/env/wait-for-connection 127.0.0.1 445 60
- name: PHPUnit
run: composer run test:files_external -- --verbose \
apps/files_external/tests/Storage/SmbTest.php \
${{ matrix.coverage && ' --coverage-clover ./clover.xml' || '' }}
- name: Upload code coverage
if: ${{ !cancelled() && matrix.coverage }}
uses: codecov/codecov-action@c16abc29c95fcf9174b58eb7e1abf4c866893bc8 # v4.1.1
with:
files: ./clover.xml
flags: phpunit-files-external-smb
files-external-smb-summary:
runs-on: ubuntu-latest-low
needs: [changes, files-external-smb]
if: always()
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.files-external-smb.result != 'success' }}; then exit 1; fi

View File

@@ -1,107 +0,0 @@
# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: PHPUnit files_external WebDAV
on:
pull_request:
schedule:
- cron: "5 2 * * *"
concurrency:
group: files-external-webdav-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '3rdparty/**'
- 'apps/files_external/**'
- 'vendor/**'
- 'vendor-bin/**'
- 'composer.json'
- 'composer.lock'
- '**.php'
files-external-webdav-apache:
runs-on: ubuntu-latest
needs: changes
if: ${{ github.repository_owner != 'nextcloud-gmbh' && needs.changes.outputs.src != 'false' }}
strategy:
matrix:
php-versions: ['8.1', '8.2', '8.3']
include:
- php-versions: '8.2'
coverage: ${{ github.event_name != 'pull_request' }}
name: php${{ matrix.php-versions }}-webdav
services:
apache:
image: ghcr.io/nextcloud/continuous-integration-webdav-apache:latest
ports:
- 8081:80
steps:
- name: Checkout server
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: ${{ matrix.php-versions }}
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, redis, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
coverage: ${{ matrix.coverage && 'xdebug' || 'none' }}
ini-file: development
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Nextcloud
run: |
composer install
./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-host=127.0.0.1 --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password
./occ config:system:set --value true --type boolean allow_local_remote_servers
./occ app:enable --force files_external
echo "<?php return ['run' => true, 'host' => 'localhost:8081/webdav/', 'user' => 'test', 'password'=>'pass', 'root' => '', 'wait' => 0];" > apps/files_external/tests/config.webdav.php
- name: Wait for WebDAV
run: |
sleep 5
curl -f -m 1 --retry-connrefused --retry 10 --retry-delay 10 http://test:pass@localhost:8081/webdav/
- name: PHPUnit
run: composer run test:files_external -- --verbose \
apps/files_external/tests/Storage/WebdavTest.php \
${{ matrix.coverage && ' --coverage-clover ./clover.xml' || '' }}
- name: Upload code coverage
if: ${{ !cancelled() && matrix.coverage }}
uses: codecov/codecov-action@c16abc29c95fcf9174b58eb7e1abf4c866893bc8 # v4.1.1
with:
files: ./clover.xml
flags: phpunit-files-external-webdav
files-external-webdav-summary:
runs-on: ubuntu-latest-low
needs: [changes, files-external-webdav-apache]
if: always()
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.files-external-webdav-apache.result != 'success' }}; then exit 1; fi

View File

@@ -1,95 +0,0 @@
# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: PHPUnit files_external generic
on:
pull_request:
schedule:
- cron: "5 2 * * *"
concurrency:
group: files-external-generic-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '3rdparty/**'
- 'apps/files_external/**'
- 'vendor/**'
- 'vendor-bin/**'
- 'composer.json'
- 'composer.lock'
files-external-generic:
runs-on: ubuntu-latest
needs: changes
if: ${{ github.repository_owner != 'nextcloud-gmbh' && needs.changes.outputs.src != 'false' }}
strategy:
matrix:
php-versions: ['8.1', '8.2', '8.3']
include:
- php-versions: '8.2'
coverage: ${{ github.event_name != 'pull_request' }}
name: php${{ matrix.php-versions }}-generic
steps:
- name: Checkout server
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: ${{ matrix.php-versions }}
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, redis, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
coverage: ${{ matrix.coverage && 'xdebug' || 'none' }}
ini-file: development
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Nextcloud
env:
OBJECT_STORE_KEY: nextcloud
OBJECT_STORE_SECRET: bWluaW8tc2VjcmV0LWtleS1uZXh0Y2xvdWQ=
run: |
composer install
./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-host=127.0.0.1 --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password
./occ app:enable --force files_external
- name: PHPUnit
run: composer run test:files_external \
${{ matrix.coverage && ' --coverage-clover ./clover.xml' || '' }}
- name: Upload code coverage
if: ${{ !cancelled() && matrix.coverage }}
uses: codecov/codecov-action@v4.1.1
with:
files: ./clover.xml
flags: phpunit-files-external-generic
files-external-summary:
runs-on: ubuntu-latest-low
needs: [changes, files-external-generic ]
if: always()
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.files-external-generic.result != 'success' }}; then exit 1; fi

View File

@@ -1,36 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Block fixup and squash commits
on:
pull_request:
types: [opened, ready_for_review, reopened, synchronize]
permissions:
contents: read
concurrency:
group: fixup-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
commit-message-check:
if: github.event.pull_request.draft == false
permissions:
pull-requests: write
name: Block fixup and squash commits
runs-on: ubuntu-latest-low
steps:
- name: Run check
uses: skjnldsv/block-fixup-merge-action@c138ea99e45e186567b64cf065ce90f7158c236a # v2
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,125 +0,0 @@
# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: DAV integration tests
on:
pull_request:
concurrency:
group: integration-caldav-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '3rdparty/**'
- '**/*.php'
- '**/lib/**'
- '**/tests/**'
- '**/vendor-bin/**'
- 'build/integration/**'
- '.php-cs-fixer.dist.php'
- 'composer.json'
- 'composer.lock'
integration-caldav:
runs-on: ubuntu-latest
needs: changes
if: needs.changes.outputs.src != 'false' && github.repository_owner != 'nextcloud-gmbh'
strategy:
# do not stop on another job's failure
fail-fast: false
matrix:
php-versions: ['8.3']
endpoint: ['old', 'new']
service: ['CalDAV', 'CardDAV']
name: ${{ matrix.service }} (${{ matrix.endpoint }} endpoint) php${{ matrix.php-versions }}
steps:
- name: Checkout server
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: ${{ matrix.php-versions }}
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, redis, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
coverage: 'none'
ini-file: development
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Python
uses: LizardByte/setup-python-action@master
with:
python-version: '2.7'
- name: Set up CalDAVTester
run: |
git clone --depth=1 https://github.com/apple/ccs-caldavtester.git CalDAVTester
git clone --depth=1 https://github.com/apple/ccs-pycalendar.git pycalendar
- name: Set up Nextcloud
run: |
mkdir data
./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-host=127.0.0.1 --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin
# disable the trashbin, so recurrent deletion of the same object works
./occ config:app:set dav calendarRetentionObligation --value=0
# Prepare users
OC_PASS=user01 ./occ user:add --password-from-env user01
OC_PASS=user02 ./occ user:add --password-from-env user02
# Prepare calendars
./occ dav:create-calendar user01 calendar
./occ dav:create-calendar user01 shared
./occ dav:create-calendar user02 calendar
# Prepare address books
./occ dav:create-addressbook user01 addressbook
./occ dav:create-addressbook user02 addressbook
- name: Run Nextcloud
run: |
php -S localhost:8888 &
- name: Run CalDAVTester
run: |
cp "apps/dav/tests/travis/caldavtest/serverinfo-${{ matrix.endpoint }}${{ matrix.endpoint == 'old' && (matrix.service == 'CardDAV' && '-carddav' || '-caldav') || '' }}-endpoint.xml" "apps/dav/tests/travis/caldavtest/serverinfo.xml"
pushd CalDAVTester
PYTHONPATH="../pycalendar/src" python testcaldav.py --print-details-onfail --basedir "../apps/dav/tests/travis/caldavtest" -o cdt.txt \
"${{ matrix.service }}/current-user-principal.xml" \
"${{ matrix.service }}/sync-report.xml" \
${{ matrix.endpoint == 'new' && format('{0}/sharing-{1}.xml', matrix.service, matrix.service == 'CalDAV' && 'calendars' || 'addressbooks') || ';' }}
popd
- name: Print Nextcloud logs
if: always()
run: |
cat data/nextcloud.log
caldav-integration-summary:
permissions:
contents: none
runs-on: ubuntu-latest-low
needs: [changes, integration-caldav]
if: always()
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.integration-caldav.result != 'success' }}; then exit 1; fi

View File

@@ -1,112 +0,0 @@
# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Litmus integration tests
on:
pull_request:
concurrency:
group: integration-litmus-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '3rdparty/**'
- '**/*.php'
- '**/lib/**'
- '**/tests/**'
- '**/vendor-bin/**'
- 'build/integration/**'
- '.php-cs-fixer.dist.php'
- 'composer.json'
- 'composer.lock'
integration-litmus:
runs-on: ubuntu-latest
needs: changes
if: needs.changes.outputs.src != 'false' && github.repository_owner != 'nextcloud-gmbh'
strategy:
# do not stop on another job's failure
fail-fast: false
matrix:
php-versions: ['8.3']
endpoint: ['webdav', 'dav']
name: Litmus WebDAV ${{ matrix.endpoint }}
steps:
- name: Checkout server
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: ${{ matrix.php-versions }}
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, redis, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
coverage: 'none'
ini-file: development
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Nextcloud
run: |
mkdir data
./occ maintenance:install \
--verbose \
--database=sqlite \
--database-name=nextcloud \
--database-user=root \
--database-pass=rootpassword \
--admin-user admin \
--admin-pass admin
./occ config:system:set trusted_domains 2 --value=host.docker.internal:8080
- name: Run Nextcloud
run: |
php -S 0.0.0.0:8080 &
- name: Run Litmus test
run: |
docker run \
--rm \
--add-host=host.docker.internal:host-gateway \
ghcr.io/nextcloud/continuous-integration-litmus-php8.3:latest \
bash -c '\
cd /tmp/litmus/litmus-0.13;
make URL=http://host.docker.internal:8080/remote.php/${{ matrix.endpoint }}${{ matrix.endpoint == 'dav' && '/files/admin' || ''}} CREDS="admin admin" TESTS="basic copymove props largefile" check;
status=$?;
cat debug.log;
exit $status;'
- name: Print Nextcloud logs
if: always()
run: cat data/nextcloud.log
integration-litmus-summary:
permissions:
contents: none
runs-on: ubuntu-latest-low
needs: [changes, integration-litmus]
if: always()
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.integration-litmus.result != 'success' }}; then exit 1; fi

View File

@@ -1,119 +0,0 @@
# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: S3 primary storage integration tests
on:
pull_request:
concurrency:
group: integration-s3-primary-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '3rdparty/**'
- '**/*.php'
- '**/lib/**'
- '**/tests/**'
- '**/vendor-bin/**'
- 'build/integration/**'
- '.php-cs-fixer.dist.php'
- 'composer.json'
- 'composer.lock'
integration-s3-primary:
runs-on: ubuntu-latest
needs: changes
if: needs.changes.outputs.src != 'false' && github.repository_owner != 'nextcloud-gmbh'
strategy:
# do not stop on another job's failure
fail-fast: false
matrix:
php-versions: ['8.1']
key: ['objectstore', 'objectstore_multibucket']
name: php${{ matrix.php-versions }}-${{ matrix.key }}-minio
services:
redis:
image: ghcr.io/nextcloud/continuous-integration-redis:latest
options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3
ports:
- 6379:6379/tcp
minio:
image: bitnami/minio
env:
MINIO_ROOT_USER: nextcloud
MINIO_ROOT_PASSWORD: bWluaW8tc2VjcmV0LWtleS1uZXh0Y2xvdWQ=
MINIO_DEFAULT_BUCKETS: nextcloud
ports:
- "9000:9000"
steps:
- name: Checkout server
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: ${{ matrix.php-versions }}
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, redis, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
coverage: 'none'
ini-file: development
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Wait for S3
run: |
sleep 10
curl -f -m 1 --retry-connrefused --retry 10 --retry-delay 10 http://localhost:9000/minio/health/ready
- name: Set up Nextcloud
run: |
mkdir data
echo '<?php $CONFIG=["${{ matrix.key }}" => ["class" => "OC\Files\ObjectStore\S3", "arguments" => ["bucket" => "nextcloud", "autocreate" => true, "key" => "nextcloud", "secret" => "bWluaW8tc2VjcmV0LWtleS1uZXh0Y2xvdWQ=", "hostname" => "localhost", "port" => 9000, "use_ssl" => false, "use_path_style" => true, "uploadPartSize" => 52428800]]];' > config/config.php
echo '<?php $CONFIG=["redis" => ["host" => "localhost", "port" => 6379], "memcache.local" => "\OC\Memcache\Redis", "memcache.distributed" => "\OC\Memcache\Redis"];' > config/redis.config.php
./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-host=127.0.0.1 --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin
php -f index.php
- name: Integration
run: |
cd build/integration
bash run.sh --tags "~@failure-s3" dav_features/webdav-related.feature
- name: S3 logs
if: always()
run: |
cat data/nextcloud.log
docker ps -a
docker ps -aq | while read container ; do IMAGE=$(docker inspect --format='{{.Config.Image}}' $container); echo $IMAGE; docker logs $container; echo "\n\n" ; done
s3-primary-integration-summary:
permissions:
contents: none
runs-on: ubuntu-latest-low
needs: [changes, integration-s3-primary]
if: always()
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.integration-s3-primary.result != 'success' }}; then exit 1; fi

View File

@@ -1,168 +0,0 @@
# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Integration sqlite
on:
pull_request:
push:
branches:
- main
- master
- stable*
permissions:
contents: read
concurrency:
group: integration-sqlite-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '3rdparty/**'
- '**/*.php'
- '**/lib/**'
- '**/tests/**'
- '**/vendor-bin/**'
- 'build/integration/**'
- '.php-cs-fixer.dist.php'
- 'composer.json'
- 'composer.lock'
integration-sqlite:
runs-on: ubuntu-latest
needs: changes
if: needs.changes.outputs.src != 'false'
strategy:
fail-fast: false
matrix:
test-suite:
- 'capabilities_features'
- 'collaboration_features'
- 'comments_features'
- 'dav_features'
- 'features'
- 'federation_features'
- '--tags ~@large files_features'
- 'filesdrop_features'
- 'openldap_features'
- 'openldap_numerical_features'
- 'ldap_features'
- 'remoteapi_features'
- 'setup_features'
- 'sharees_features'
- 'sharing_features'
- 'videoverification_features'
php-versions: ['8.2']
spreed-versions: ['main']
services:
redis:
image: ghcr.io/nextcloud/continuous-integration-redis:latest
options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3
ports:
- 6379:6379/tcp
openldap:
image: ghcr.io/nextcloud/continuous-integration-openldap:openldap-7
ports:
- 389:389
env:
SLAPD_DOMAIN: nextcloud.ci
SLAPD_ORGANIZATION: Nextcloud
SLAPD_PASSWORD: admin
SLAPD_ADDITIONAL_MODULES: memberof
steps:
- name: Checkout server
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
submodules: true
- name: Checkout Talk app
if: ${{ matrix.test-suite == 'videoverification_features' }}
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
repository: nextcloud/spreed
path: apps/spreed
ref: ${{ matrix.spreed-versions }}
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: ${{ matrix.php-versions }}
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, imagick, intl, json, ldap, libxml, mbstring, openssl, pcntl, posix, redis, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
coverage: none
ini-file: development
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up production dependencies
run: composer i --no-dev
- name: Set up behat dependencies
working-directory: build/integration
run: composer i
- name: Set up Talk dependencies
if: ${{ matrix.test-suite == 'videoverification_features' }}
working-directory: apps/spreed
run: composer i --no-dev
- name: Set up Nextcloud
run: |
mkdir data
./occ maintenance:install --verbose ${{ contains(matrix.test-suite,'ldap') && '--data-dir=/dev/shm/nc_int' || '' }} --database=sqlite --database-name=nextcloud --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin
./occ config:system:set hashing_default_password --value=true --type=boolean
- name: Configure caching
if: ${{ contains(matrix.test-suite,'ldap') }}
run: |
./occ config:system:set redis host --value=localhost
./occ config:system:set redis port --value=6379 --type=integer
./occ config:system:set redis timeout --value=0 --type=integer
./occ config:system:set memcache.local --value='\OC\Memcache\Redis'
./occ config:system:set memcache.distributed --value='\OC\Memcache\Redis'
- name: Run integration
working-directory: build/integration
env:
LDAP_HOST: localhost
run: bash run.sh ${{ matrix.test-suite }} no-tail-log
- name: Print logs
if: always()
run: |
cat data/nextcloud.log
docker ps -a
docker ps -aq | while read container ; do IMAGE=$(docker inspect --format='{{.Config.Image}}' $container); echo $IMAGE; docker logs $container; echo "\n\n" ; done
summary:
permissions:
contents: none
runs-on: ubuntu-latest-low
needs: [changes, integration-sqlite]
if: always()
name: integration-sqlite-summary
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.integration-sqlite.result != 'success' }}; then exit 1; fi

View File

@@ -1,95 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Lint eslint
on: pull_request
permissions:
contents: read
concurrency:
group: lint-eslint-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '**/src/**'
- '**/appinfo/info.xml'
- 'package.json'
- 'package-lock.json'
- 'tsconfig.json'
- '.eslintrc.*'
- '.eslintignore'
- '**.js'
- '**.ts'
- '**.vue'
lint:
runs-on: ubuntu-latest
needs: changes
if: needs.changes.outputs.src != 'false'
name: NPM lint
steps:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Read package.json node and npm engines version
uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3
id: versions
with:
fallbackNode: '^20'
fallbackNpm: '^10'
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v3
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 dependencies
env:
CYPRESS_INSTALL_BINARY: 0
PUPPETEER_SKIP_DOWNLOAD: true
run: npm ci
- name: Lint
run: npm run lint
summary:
permissions:
contents: none
runs-on: ubuntu-latest-low
needs: [changes, lint]
if: always()
# This is the summary, we just avoid to rename it so that branch protection rules still match
name: eslint
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.lint.result != 'success' }}; then exit 1; fi

View File

@@ -1,82 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Lint php-cs
on: pull_request
permissions:
contents: read
concurrency:
group: lint-php-cs-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '3rdparty/**'
- '**/lib/**'
- '**/tests/**'
- '**/vendor-bin/**'
- '.php-cs-fixer.dist.php'
- 'composer.json'
- 'composer.lock'
- '**.php'
lint:
runs-on: ubuntu-latest
name: PHP CS fixer lint
steps:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Set up php8.1
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: 8.1
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
coverage: none
ini-file: development
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Install dependencies
run: composer i
- name: Lint
run: composer run cs:check || ( echo 'Please run `composer run cs:fix` to format your code' && exit 1 )
summary:
permissions:
contents: none
runs-on: ubuntu-latest-low
needs: [changes, lint]
if: always()
# This is the summary, we just avoid to rename it so that branch protection rules still match
name: php-cs
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.lint.result != 'success' }}; then exit 1; fi

View File

@@ -1,82 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Lint php
on: pull_request
permissions:
contents: read
concurrency:
group: lint-php-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '3rdparty/**'
- '**/lib/**'
- '**/tests/**'
- '**/vendor-bin/**'
- '.php-cs-fixer.dist.php'
- 'composer.json'
- 'composer.lock'
- '**.php'
lint:
runs-on: ubuntu-latest
needs: changes
if: needs.changes.outputs.src != 'false'
strategy:
matrix:
php-versions: [ '8.1', '8.2', '8.3' ]
name: php-lint
steps:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: ${{ matrix.php-versions }}
coverage: none
ini-file: development
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Lint
run: composer run lint
summary:
permissions:
contents: none
runs-on: ubuntu-latest-low
needs: [changes, lint]
if: always()
name: php-lint-summary
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.lint.result != 'success' }}; then exit 1; fi

View File

@@ -1,173 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Node tests
on:
pull_request:
schedule:
- cron: "5 2 * * *"
permissions:
contents: read
concurrency:
group: node-tests-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '**/__tests__/**'
- '**/__mocks__/**'
- 'apps/*/src/**'
- 'apps/*/appinfo/info.xml'
- 'core/src/**'
- 'package.json'
- 'package-lock.json'
- 'tsconfig.json'
- '**.js'
- '**.ts'
- '**.vue'
versions:
runs-on: ubuntu-latest-low
needs: changes
if: ${{ github.repository_owner != 'nextcloud-gmbh' && needs.changes.outputs.src != 'false' }}
outputs:
nodeVersion: ${{ steps.versions.outputs.nodeVersion }}
npmVersion: ${{ steps.versions.outputs.npmVersion }}
steps:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Read package.json node and npm engines version
uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3
id: versions
with:
fallbackNode: '^20'
fallbackNpm: '^10'
test:
runs-on: ubuntu-latest
needs: [versions, changes]
if: ${{ needs.versions.result != 'failure' && needs.changes.outputs.src != 'false' }}
env:
CYPRESS_INSTALL_BINARY: 0
PUPPETEER_SKIP_DOWNLOAD: true
steps:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Set up node ${{ needs.versions.outputs.nodeVersion }}
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: ${{ needs.versions.outputs.nodeVersion }}
- name: Set up npm ${{ needs.versions.outputs.npmVersion }}
run: npm i -g 'npm@${{ needs.versions.outputs.npmVersion }}'
- name: Install dependencies & build
run: |
npm ci
npm run build --if-present
- name: Test and process coverage
run: npm run test:coverage --if-present
- name: Collect coverage
uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # v4.3.1
with:
files: ./coverage/lcov.info
jsunit:
runs-on: ubuntu-latest
needs: [versions, changes]
if: ${{ needs.versions.result != 'failure' && needs.changes.outputs.src != 'false' }}
env:
CYPRESS_INSTALL_BINARY: 0
steps:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Set up node ${{ needs.versions.outputs.nodeVersion }}
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: ${{ needs.versions.outputs.nodeVersion }}
- name: Set up npm ${{ needs.versions.outputs.npmVersion }}
run: npm i -g 'npm@${{ needs.versions.outputs.npmVersion }}'
- name: Install dependencies
run: npm ci
- name: Test
run: npm run test:jsunit
handlebars:
runs-on: ubuntu-latest
needs: [versions, changes]
if: ${{ needs.versions.result != 'failure' && needs.changes.outputs.src != 'false' }}
env:
CYPRESS_INSTALL_BINARY: 0
PUPPETEER_SKIP_DOWNLOAD: true
steps:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Set up node ${{ needs.versions.outputs.nodeVersion }}
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: ${{ needs.versions.outputs.nodeVersion }}
- name: Set up npm ${{ needs.versions.outputs.npmVersion }}
run: npm i -g 'npm@${{ needs.versions.outputs.npmVersion }}'
- name: Install dependencies
run: npm ci
- name: Run compile
run: ./build/compile-handlebars-templates.sh
summary:
permissions:
contents: none
runs-on: ubuntu-latest-low
needs: [changes, test, jsunit, handlebars]
if: always()
name: node-test-summary
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.test.result != 'success' && needs.jsunit.result != 'success' && needs.handlebars.result != 'success' }}; then exit 1; fi

View File

@@ -1,104 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Node
on: pull_request
permissions:
contents: read
concurrency:
group: node-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '**/src/**'
- '**/appinfo/info.xml'
- 'package.json'
- 'package-lock.json'
- 'tsconfig.json'
- '**.js'
- '**.ts'
- '**.vue'
- 'core/css/*'
- 'core/img/**'
build:
runs-on: ubuntu-latest
needs: changes
if: needs.changes.outputs.src != 'false'
name: NPM build
steps:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Read package.json node and npm engines version
uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3
id: versions
with:
fallbackNode: '^20'
fallbackNpm: '^10'
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v3
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 dependencies & build
env:
CYPRESS_INSTALL_BINARY: 0
PUPPETEER_SKIP_DOWNLOAD: true
run: |
npm ci
npm run build --if-present
- name: Check webpack build changes
run: |
bash -c "[[ ! \"`git status --porcelain `\" ]] || (echo 'Please recompile and commit the assets, see the section \"Show changes on failure\" for details' && exit 1)"
- name: Show changes on failure
if: failure()
run: |
git status
git --no-pager diff
exit 1 # make it red to grab attention
summary:
permissions:
contents: none
runs-on: ubuntu-latest-low
needs: [changes, build]
if: always()
# This is the summary, we just avoid to rename it so that branch protection rules still match
name: node
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.build.result != 'success' }}; then exit 1; fi

View File

@@ -1,75 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Npm audit fix and compile
on:
workflow_dispatch:
schedule:
# At 2:30 on Sundays
- cron: '30 2 * * 0'
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
branches: ['main', 'master', 'stable29', 'stable28', 'stable27']
name: npm-audit-fix-${{ matrix.branches }}
steps:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
ref: ${{ matrix.branches }}
- name: Read package.json node and npm engines version
uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3
id: versions
with:
fallbackNode: '^20'
fallbackNpm: '^10'
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v3
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: Fix npm audit
id: npm-audit
uses: nextcloud-libraries/npm-audit-action@2a60bd2e79cc77f2cc4d9a3fe40f1a69896f3a87 # v0.1.0
- name: Run npm ci and npm run build
if: always()
env:
CYPRESS_INSTALL_BINARY: 0
run: |
npm ci
npm run build --if-present
- name: Create Pull Request
if: always()
uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c # v6.1.0
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
commit-message: 'fix(deps): Fix npm audit'
committer: GitHub <noreply@github.com>
author: nextcloud-command <nextcloud-command@users.noreply.github.com>
signoff: true
branch: automated/noid/${{ matrix.branches }}-fix-npm-audit
title: '[${{ matrix.branches }}] Fix npm audit'
body: ${{ steps.npm-audit.outputs.markdown }}
labels: |
dependencies
3. to review

View File

@@ -1,127 +0,0 @@
# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Object storage azure
on:
pull_request:
schedule:
- cron: "15 2 * * *"
concurrency:
group: object-storage-azure-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '3rdparty/**'
- '**/appinfo/**'
- '**/lib/**'
- '**/templates/**'
- '**/tests/**'
- 'vendor/**'
- 'vendor-bin/**'
- '.php-cs-fixer.dist.php'
- 'composer.json'
- 'composer.lock'
- '**.php'
azure-primary-tests:
runs-on: ubuntu-latest
needs: changes
if: ${{ github.repository_owner != 'nextcloud-gmbh' && needs.changes.outputs.src != 'false' }}
strategy:
matrix:
php-versions: ['8.1', '8.2', '8.3']
include:
- php-versions: '8.3'
coverage: true
name: php${{ matrix.php-versions }}-azure
services:
azurite:
image: mcr.microsoft.com/azure-storage/azurite
env:
AZURITE_ACCOUNTS: nextcloud:bmV4dGNsb3Vk
ports:
- 10000:10000
options: --health-cmd="nc 127.0.0.1 10000 -z" --health-interval=1s --health-retries=30
cache:
image: ghcr.io/nextcloud/continuous-integration-redis:latest
ports:
- 6379:6379/tcp
options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3
steps:
- name: Checkout server
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: ${{ matrix.php-versions }}
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, redis, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
coverage: ${{ matrix.coverage && 'xdebug' || 'none' }}
ini-file: development
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Nextcloud
env:
OBJECT_STORE: azure
OBJECT_STORE_KEY: nextcloud
OBJECT_STORE_SECRET: bmV4dGNsb3Vk
run: |
composer install
cp tests/redis.config.php config/
cp tests/preseed-config.php config/config.php
./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-host=127.0.0.1 --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password
php -f tests/enable_all.php | grep -i -C9999 error && echo "Error during app setup" && exit 1 || exit 0
- name: PHPUnit
env:
OBJECT_STORE: azure
OBJECT_STORE_KEY: nextcloud
OBJECT_STORE_SECRET: bmV4dGNsb3Vk
run: composer run test -- --group PRIMARY-azure ${{ matrix.coverage && ' --coverage-clover ./clover.xml' || '' }}
- name: Upload code coverage
if: ${{ !cancelled() && matrix.coverage }}
uses: codecov/codecov-action@v4.1.1
with:
files: ./clover.xml
flags: phpunit-azure
- name: Azurite logs
if: always()
run: |
docker ps -a
docker ps -aq | while read container ; do IMAGE=$(docker inspect --format='{{.Config.Image}}' $container); echo $IMAGE; docker logs $container; echo "\n\n" ; done
azure-primary-summary:
runs-on: ubuntu-latest-low
needs: [changes, azure-primary-tests]
if: always()
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.azure-primary-tests.result != 'success' }}; then exit 1; fi

View File

@@ -1,133 +0,0 @@
# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Object storage S3
on:
pull_request:
schedule:
- cron: "15 2 * * *"
concurrency:
group: object-storage-s3-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '3rdparty/**'
- '**/appinfo/**'
- '**/lib/**'
- '**/templates/**'
- '**/tests/**'
- 'vendor/**'
- 'vendor-bin/**'
- '.php-cs-fixer.dist.php'
- 'composer.json'
- 'composer.lock'
- '**.php'
s3-primary-tests-minio:
runs-on: ubuntu-22.04
needs: changes
if: ${{ github.repository_owner != 'nextcloud-gmbh' && needs.changes.outputs.src != 'false' }}
strategy:
matrix:
php-versions: ['8.1', '8.2', '8.3']
include:
- php-versions: '8.3'
coverage: true
name: php${{ matrix.php-versions }}-s3
services:
cache:
image: ghcr.io/nextcloud/continuous-integration-redis:latest
ports:
- 6379:6379/tcp
options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3
minio:
image: bitnami/minio
env:
MINIO_ROOT_USER: nextcloud
MINIO_ROOT_PASSWORD: bWluaW8tc2VjcmV0LWtleS1uZXh0Y2xvdWQ=
MINIO_DEFAULT_BUCKETS: nextcloud
ports:
- "9000:9000"
steps:
- name: Checkout server
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: ${{ matrix.php-versions }}
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, redis, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
coverage: ${{ matrix.coverage && 'xdebug' || 'none' }}
ini-file: development
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Nextcloud
env:
OBJECT_STORE: s3
OBJECT_STORE_KEY: nextcloud
OBJECT_STORE_SECRET: bWluaW8tc2VjcmV0LWtleS1uZXh0Y2xvdWQ=
run: |
composer install
cp tests/redis.config.php config/
cp tests/preseed-config.php config/config.php
./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-host=127.0.0.1 --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password
php -f tests/enable_all.php | grep -i -C9999 error && echo "Error during app setup" && exit 1 || exit 0
- name: Wait for S3
run: |
sleep 10
curl -f -m 1 --retry-connrefused --retry 10 --retry-delay 10 http://localhost:9000/minio/health/ready
- name: PHPUnit
env:
OBJECT_STORE: s3
OBJECT_STORE_KEY: nextcloud
OBJECT_STORE_SECRET: bWluaW8tc2VjcmV0LWtleS1uZXh0Y2xvdWQ=
run: composer run test -- --group PRIMARY-s3 ${{ matrix.coverage && ' --coverage-clover ./clover.xml' || '' }}
- name: Upload code coverage
if: ${{ !cancelled() && matrix.coverage }}
uses: codecov/codecov-action@v4.1.1
with:
files: ./clover.xml
flags: phpunit-s3
- name: S3 logs
if: always()
run: |
docker ps -a
docker ps -aq | while read container ; do IMAGE=$(docker inspect --format='{{.Config.Image}}' $container); echo $IMAGE; docker logs $container; echo "\n\n" ; done
s3-primary-summary:
runs-on: ubuntu-latest-low
needs: [changes,s3-primary-tests-minio]
if: always()
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.s3-primary-tests-minio.result != 'success' }}; then exit 1; fi

View File

@@ -1,123 +0,0 @@
# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Object storage Swift
on:
pull_request:
schedule:
- cron: "15 2 * * *"
concurrency:
group: object-storage-swift-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '3rdparty/**'
- '**/appinfo/**'
- '**/lib/**'
- '**/templates/**'
- '**/tests/**'
- 'vendor/**'
- 'vendor-bin/**'
- '.php-cs-fixer.dist.php'
- 'composer.json'
- 'composer.lock'
- '**.php'
swift-primary-tests:
runs-on: ubuntu-latest
needs: changes
if: ${{ github.repository_owner != 'nextcloud-gmbh' && needs.changes.outputs.src != 'false' }}
strategy:
matrix:
php-versions: ['8.1', '8.2', '8.3']
include:
- php-versions: '8.3'
coverage: true
name: php${{ matrix.php-versions }}-swift
services:
cache:
image: ghcr.io/nextcloud/continuous-integration-redis:latest
ports:
- 6379:6379/tcp
options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3
swift:
image: ghcr.io/cscfi/docker-keystone-swift
ports:
- 5000:5000
- 8080:8080
steps:
- name: Checkout server
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: ${{ matrix.php-versions }}
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, redis, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
coverage: ${{ matrix.coverage && 'xdebug' || 'none' }}
ini-file: development
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Nextcloud
env:
OBJECT_STORE: swift
OBJECT_STORE_SECRET: veryfast
run: |
composer install
cp tests/redis.config.php config/
cp tests/preseed-config.php config/config.php
./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-host=127.0.0.1 --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password
php -f tests/enable_all.php | grep -i -C9999 error && echo "Error during app setup" && exit 1 || exit 0
- name: PHPUnit
env:
OBJECT_STORE: swift
OBJECT_STORE_SECRET: veryfast
run: composer run test -- --group PRIMARY-swift ${{ matrix.coverage && ' --coverage-clover ./clover.xml' || '' }}
- name: Upload code coverage
if: ${{ !cancelled() && matrix.coverage }}
uses: codecov/codecov-action@v4.1.1
with:
files: ./clover.xml
flags: phpunit-swift
- name: Swift logs
if: always()
run: |
docker ps -a
docker ps -aq | while read container ; do IMAGE=$(docker inspect --format='{{.Config.Image}}' $container); echo $IMAGE; docker logs $container; echo "\n\n" ; done
swift-primary-summary:
runs-on: ubuntu-latest-low
needs: [changes,swift-primary-tests]
if: always()
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.swift-primary-tests.result != 'success' }}; then exit 1; fi

View File

@@ -1,45 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-FileCopyrightText: 2024 Arthur Schiwon <blizzz@arthur-schiwon.de>
# SPDX-License-Identifier: MIT
name: OpenAPI
on: pull_request
permissions:
contents: read
concurrency:
group: openapi-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
openapi:
runs-on: ubuntu-latest
if: ${{ github.repository_owner != 'nextcloud-gmbh' }}
steps:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Set up php
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: '8.2'
extensions: ctype, curl, dom, fileinfo, gd, json, libxml, mbstring, openssl, pcntl, pdo, posix, session, simplexml, xml, xmlreader, xmlwriter, zip, zlib
coverage: none
ini-file: development
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up dependencies
run: composer i
- name: OpenAPI checker
run: build/openapi-checker.sh

View File

@@ -1,114 +0,0 @@
# SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Performance testing
on:
pull_request:
concurrency:
group: performance-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
performance-testing:
runs-on: ubuntu-latest
if: ${{ github.repository_owner != 'nextcloud-gmbh' }}
strategy:
fail-fast: false
matrix:
php-versions: ['8.1']
name: performance-${{ matrix.php-versions }}
steps:
- name: Checkout server before PR
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
submodules: true
ref: ${{ github.event.pull_request.base.ref }}
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: ${{ matrix.php-versions }}
extensions: mbstring, fileinfo, intl, sqlite, pdo_sqlite, zip, gd
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Nextcloud
run: |
mkdir data
./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-host=127.0.0.1 --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password
php -S localhost:8080 &
- name: Apply blueprint
uses: icewind1991/blueprint@v0.1.2
with:
blueprint: tests/blueprints/basic.toml
ref: ${{ github.event.pull_request.head.ref }}
- name: Run before measurements
uses: nextcloud/profiler@6801ee10fc80f10b444388fb6ca9b36ad8a2ea83
with:
run: |
curl -s -X PROPFIND -u test:test http://localhost:8080/remote.php/dav/files/test
curl -s -u test:test http://localhost:8080/remote.php/dav/files/test/test.txt
curl -s -X PROPFIND -u test:test http://localhost:8080/remote.php/dav/files/test/many_files
curl -s -u test:test -T README.md http://localhost:8080/remote.php/dav/files/test/new_file.txt
curl -s -u test:test -X DELETE http://localhost:8080/remote.php/dav/files/test/new_file.txt
output: before.json
profiler-branch: master
- name: Apply PR
run: |
git remote add pr '${{ github.event.pull_request.head.repo.clone_url }}'
git fetch pr '${{ github.event.pull_request.head.ref }}'
git checkout -b 'pr/${{ github.event.pull_request.head.ref }}'
git submodule update
./occ upgrade
- name: Run after measurements
id: compare
uses: nextcloud/profiler@6801ee10fc80f10b444388fb6ca9b36ad8a2ea83
with:
run: |
curl -s -X PROPFIND -u test:test http://localhost:8080/remote.php/dav/files/test
curl -s -u test:test http://localhost:8080/remote.php/dav/files/test/test.txt
curl -s -X PROPFIND -u test:test http://localhost:8080/remote.php/dav/files/test/many_files
curl -s -u test:test -T README.md http://localhost:8080/remote.php/dav/files/test/new_file.txt
curl -s -u test:test -X DELETE http://localhost:8080/remote.php/dav/files/test/new_file.txt
output: after.json
profiler-branch: master
compare-with: before.json
- name: Upload profiles
if: always()
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808
with:
name: profiles
path: |
before.json
after.json
- uses: actions/github-script@v7
if: failure() && steps.compare.outcome == 'failure'
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
let comment = `Possible performance regression detected\n`;
comment += `<details><summary>Show Output</summary>
\`\`\`
${{ steps.compare.outputs.compare }}
\`\`\`
</details>`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
})

View File

@@ -1,66 +0,0 @@
# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: PHPUnit 32bits
on:
pull_request:
paths:
- 'version.php'
- '.github/workflows/phpunit-32bits.yml'
workflow_dispatch:
schedule:
- cron: "15 1 * * 1-6"
permissions:
contents: read
concurrency:
group: phpunit-32bits-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
phpunit-32bits:
runs-on: ubuntu-latest
if: ${{ github.repository_owner != 'nextcloud-gmbh' }}
container: shivammathur/node:latest-i386
strategy:
matrix:
php-versions: ['8.1','8.3']
steps:
- name: Checkout server
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
submodules: true
- name: Install tools
run: |
sudo apt-get update
sudo apt-get install -y ffmpeg imagemagick libmagickcore-6.q16-3-extra
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: ${{ matrix.php-versions }}
extensions: ctype, curl, dom, fileinfo, gd, imagick, intl, json, mbstring, openssl, pdo_sqlite, posix, sqlite, xml, zip, apcu
coverage: none
ini-file: development
ini-values:
apc.enabled=on, apc.enable_cli=on, disable_functions= # https://github.com/shivammathur/setup-php/discussions/573
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Nextcloud
env:
DB_PORT: 4444
run: |
composer install
mkdir data
./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=autotest --database-pass=rootpassword --admin-user admin --admin-pass admin
php -f index.php
- name: PHPUnit
run: composer run test -- --exclude-group PRIMARY-azure,PRIMARY-s3,PRIMARY-swift,Memcached,Redis,RoutingWeirdness

View File

@@ -1,142 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: PHPUnit MariaDB
on:
pull_request:
schedule:
- cron: "5 2 * * *"
permissions:
contents: read
concurrency:
group: phpunit-mariadb-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '3rdparty/**'
- '**/appinfo/**'
- '**/lib/**'
- '**/templates/**'
- '**/tests/**'
- 'vendor/**'
- 'vendor-bin/**'
- '.php-cs-fixer.dist.php'
- 'composer.json'
- 'composer.lock'
- '**.php'
phpunit-mariadb:
runs-on: ubuntu-latest
needs: changes
if: needs.changes.outputs.src != 'false'
strategy:
matrix:
php-versions: ['8.1']
mariadb-versions: ['10.3', '10.6', '10.11', '11.4']
include:
- php-versions: '8.3'
mariadb-versions: '10.11'
coverage: ${{ github.event_name != 'pull_request' }}
name: MariaDB ${{ matrix.mariadb-versions }} (PHP ${{ matrix.php-versions }}) - database tests
services:
cache:
image: ghcr.io/nextcloud/continuous-integration-redis:latest
ports:
- 6379:6379/tcp
options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3
mariadb:
image: mariadb:${{ matrix.mariadb-versions }}
ports:
- 4444:3306/tcp
env:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_USER: oc_autotest
MYSQL_PASSWORD: nextcloud
MYSQL_DATABASE: oc_autotest
options: --health-cmd="${{ matrix.mariadb-versions <= 10.4 && 'mysqladmin' || 'mariadb-admin'}} ping" --health-interval 5s --health-timeout 2s --health-retries 5
steps:
- name: Checkout server
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: ${{ matrix.php-versions }}
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, redis, session, simplexml, xmlreader, xmlwriter, zip, zlib, mysql, pdo_mysql
coverage: ${{ matrix.coverage && 'xdebug' || 'none' }}
ini-file: development
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up dependencies
run: composer i
- name: Enable ONLY_FULL_GROUP_BY MariaDB option
run: |
echo "SET GLOBAL sql_mode=(SELECT CONCAT(@@sql_mode,',ONLY_FULL_GROUP_BY'));" | mysql -h 127.0.0.1 -P 4444 -u root -prootpassword
echo 'SELECT @@sql_mode;' | mysql -h 127.0.0.1 -P 4444 -u root -prootpassword
- name: Set up Nextcloud
env:
DB_PORT: 4444
run: |
mkdir data
cp tests/redis.config.php config/
cp tests/preseed-config.php config/config.php
./occ maintenance:install --verbose --database=mysql --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin
php -f tests/enable_all.php | grep -i -C9999 error && echo "Error during app setup" && exit 1 || exit 0
- name: PHPUnit
run: composer run test:db ${{ matrix.coverage && ' -- --coverage-clover ./clover.db.xml' || '' }}
- name: Upload db code coverage
if: ${{ !cancelled() && matrix.coverage }}
uses: codecov/codecov-action@v4.1.1
with:
files: ./clover.db.xml
flags: phpunit-mariadb
summary:
permissions:
contents: none
runs-on: ubuntu-latest-low
needs: [changes, phpunit-mariadb]
if: always()
name: phpunit-mariadb-summary
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.phpunit-mariadb.result != 'success' }}; then exit 1; fi

View File

@@ -1,126 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: PHPUnit memcached
on:
pull_request:
schedule:
- cron: "5 2 * * *"
permissions:
contents: read
concurrency:
group: phpunit-memcached-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '3rdparty/**'
- '**/appinfo/**'
- '**/lib/**'
- '**/templates/**'
- '**/tests/**'
- 'vendor/**'
- 'vendor-bin/**'
- '.php-cs-fixer.dist.php'
- 'composer.json'
- 'composer.lock'
- '**.php'
phpunit-memcached:
runs-on: ubuntu-latest
needs: changes
if: needs.changes.outputs.src != 'false'
strategy:
matrix:
php-versions: ['8.1', '8.2', '8.3']
include:
- php-versions: '8.2'
coverage: ${{ github.event_name != 'pull_request' }}
name: Memcached (PHP ${{ matrix.php-versions }})
services:
memcached:
image: ghcr.io/nextcloud/continuous-integration-redis:latest
ports:
- 11212:11212/tcp
- 11212:11212/udp
steps:
- name: Checkout server
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: ${{ matrix.php-versions }}
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, memcached, openssl, pcntl, posix, redis, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
coverage: ${{ matrix.coverage && 'xdebug' || 'none' }}
ini-file: development
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up dependencies
run: composer i
- name: Set up Nextcloud
run: |
mkdir data
cp tests/preseed-config.php config/config.php
./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin
php -f tests/enable_all.php | grep -i -C9999 error && echo "Error during app setup" && exit 1 || exit 0
- name: PHPUnit memcached tests
run: composer run test -- --group Memcache,Memcached ${{ matrix.coverage && '--coverage-clover ./clover.xml' || '' }}
- name: Upload code coverage
if: ${{ !cancelled() && matrix.coverage }}
uses: codecov/codecov-action@v4.1.1
with:
files: ./clover.xml
flags: phpunit-memcached
- name: Print logs
if: always()
run: |
cat data/nextcloud.log
summary:
permissions:
contents: none
runs-on: ubuntu-latest-low
needs: [changes, phpunit-memcached]
if: always()
name: phpunit-memcached-summary
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.phpunit-memcached.result != 'success' }}; then exit 1; fi

View File

@@ -1,147 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: PHPUnit mysql
on:
pull_request:
schedule:
- cron: "5 2 * * *"
permissions:
contents: read
concurrency:
group: phpunit-mysql-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src }}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '3rdparty/**'
- '**/appinfo/**'
- '**/lib/**'
- '**/templates/**'
- '**/tests/**'
- 'vendor/**'
- 'vendor-bin/**'
- '.php-cs-fixer.dist.php'
- 'composer.json'
- 'composer.lock'
- '**.php'
phpunit-mysql:
runs-on: ubuntu-latest
needs: changes
if: needs.changes.outputs.src != 'false'
strategy:
matrix:
php-versions: ['8.1']
mysql-versions: ['8.0', '8.4']
include:
- mysql-versions: '8.0'
php-versions: '8.3'
coverage: ${{ github.event_name != 'pull_request' }}
name: MySQL ${{ matrix.mysql-versions }} (PHP ${{ matrix.php-versions }}) - database tests
services:
cache:
image: ghcr.io/nextcloud/continuous-integration-redis:latest
ports:
- 6379:6379/tcp
options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3
mysql:
image: ghcr.io/nextcloud/continuous-integration-mysql-${{ matrix.mysql-versions }}:latest
ports:
- 4444:3306/tcp
env:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_USER: oc_autotest
MYSQL_PASSWORD: nextcloud
MYSQL_DATABASE: oc_autotest
options: --health-cmd="mysqladmin ping" --health-interval 5s --health-timeout 2s --health-retries 10
steps:
- name: Checkout server
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: ${{ matrix.php-versions }}
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, redis, session, simplexml, xmlreader, xmlwriter, zip, zlib, mysql, pdo_mysql
coverage: ${{ matrix.coverage && 'xdebug' || 'none' }}
ini-file: development
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up dependencies
run: composer i
- name: Enable ONLY_FULL_GROUP_BY MySQL option
run: |
echo "SET GLOBAL sql_mode=(SELECT CONCAT(@@sql_mode,',ONLY_FULL_GROUP_BY'));" | mysql -h 127.0.0.1 -P 4444 -u root -prootpassword
echo "SELECT @@sql_mode;" | mysql -h 127.0.0.1 -P 4444 -u root -prootpassword
- name: Set up Nextcloud
env:
DB_PORT: 4444
run: |
mkdir data
cp tests/redis.config.php config/
cp tests/preseed-config.php config/config.php
./occ maintenance:install --verbose --database=mysql --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin
php -f tests/enable_all.php | grep -i -C9999 error && echo "Error during app setup" && exit 1 || exit 0
- name: PHPUnit
run: composer run test:db ${{ matrix.coverage && ' -- --coverage-clover ./clover.db.xml' || '' }}
- name: Upload db code coverage
if: ${{ !cancelled() && matrix.coverage }}
uses: codecov/codecov-action@v4.1.1
with:
files: ./clover.db.xml
flags: phpunit-mysql
- name: Print logs
if: always()
run: |
cat data/nextcloud.log
summary:
permissions:
contents: none
runs-on: ubuntu-latest-low
needs: [changes, phpunit-mysql]
if: always()
name: phpunit-mysql-summary
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.phpunit-mysql.result != 'success' }}; then exit 1; fi

View File

@@ -1,131 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
#
# This is the testsuite running all non-database agnostic unit tests
name: PHPUnit nodb
on:
pull_request:
schedule:
- cron: "5 2 * * *"
permissions:
contents: read
concurrency:
group: phpunit-nodb-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src }}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '3rdparty/**'
- '**/appinfo/**'
- '**/lib/**'
- '**/templates/**'
- '**/tests/**'
- 'vendor/**'
- 'vendor-bin/**'
- '.php-cs-fixer.dist.php'
- 'composer.json'
- 'composer.lock'
- '**.php'
phpunit-nodb:
runs-on: ubuntu-latest
needs: changes
if: needs.changes.outputs.src != 'false'
strategy:
matrix:
php-versions: ['8.1', '8.2', '8.3']
include:
- php-versions: '8.2'
coverage: ${{ github.event_name != 'pull_request' }}
name: No DB unit tests (PHP ${{ matrix.php-versions }})
services:
cache:
image: ghcr.io/nextcloud/continuous-integration-redis:latest
ports:
- 6379:6379/tcp
options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3
steps:
- name: Checkout server
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: ${{ matrix.php-versions }}
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, imagick, intl, json, libxml, mbstring, openssl, pcntl, posix, redis, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
coverage: ${{ matrix.coverage && 'xdebug' || 'none' }}
ini-file: development
# Required for tests that use pcntl
ini-values: disable_functions=""
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up dependencies
run: composer i
- name: Set up Nextcloud
run: |
mkdir data
cp tests/redis.config.php config/
cp tests/preseed-config.php config/config.php
./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin
php -f tests/enable_all.php | grep -i -C9999 error && echo "Error during app setup" && exit 1 || exit 0
- name: PHPUnit nodb testsuite
run: composer run test -- --exclude-group DB,SLOWDB ${{ matrix.coverage && ' --coverage-clover ./clover.nodb.xml' || '' }}
- name: Upload nodb code coverage
if: ${{ !cancelled() && matrix.coverage }}
uses: codecov/codecov-action@v4.1.1
with:
files: ./clover.nodb.xml
flags: phpunit-nodb
- name: Print logs
if: always()
run: |
cat data/nextcloud.log
summary:
permissions:
contents: none
runs-on: ubuntu-latest-low
needs: [changes, phpunit-nodb]
if: always()
name: phpunit-nodb-summary
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.phpunit-nodb.result != 'success' }}; then exit 1; fi

View File

@@ -54,12 +54,16 @@ jobs:
if: needs.changes.outputs.src != 'false' && ${{ github.repository_owner != 'nextcloud-gmbh' }}
strategy:
fail-fast: false
matrix:
oracle-versions: ['11']
php-versions: ['8.1', '8.2', '8.3']
include:
- php-versions: '8.3'
coverage: ${{ github.event_name != 'pull_request' }}
- oracle-versions: '18'
php-versions: '8.1'
# coverage: ${{ github.event_name != 'pull_request' }}
# - oracle-versions: '21'
# php-versions: '8.2'
# - oracle-versions: '23'
# php-versions: '8.3'
name: Oracle ${{ matrix.oracle-versions }} (PHP ${{ matrix.php-versions }}) - database tests
@@ -71,23 +75,21 @@ jobs:
options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3
oracle:
image: ghcr.io/gvenzl/oracle-xe:${{ matrix.oracle-versions }}
image: ghcr.io/gvenzl/oracle-${{ matrix.oracle-versions < 23 && 'xe' || 'free' }}:${{ matrix.oracle-versions }}
# Provide passwords and other environment variables to container
env:
ORACLE_RANDOM_PASSWORD: true
APP_USER: oc_autotest
APP_USER_PASSWORD: nextcloud
ORACLE_PASSWORD: oracle
# Forward Oracle port
ports:
- 4444:1521/tcp
- 1521:1521
# Provide healthcheck script options for startup
options: >-
--health-cmd healthcheck.sh
--health-interval 10s
--health-timeout 5s
--health-interval 20s
--health-timeout 10s
--health-retries 10
steps:
@@ -112,12 +114,12 @@ jobs:
- name: Set up Nextcloud
env:
DB_PORT: 4444
DB_PORT: 1521
run: |
mkdir data
cp tests/redis.config.php config/
cp tests/preseed-config.php config/config.php
./occ maintenance:install --verbose --database=oci --database-name=XE --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=oc_autotest --database-pass=nextcloud --admin-user admin --admin-pass admin
./occ maintenance:install --verbose --database=oci --database-name=${{ matrix.oracle-versions < 23 && 'XE' || 'FREE' }} --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=system --database-pass=oracle --admin-user admin --admin-pass admin
php -f tests/enable_all.php | grep -i -C9999 error && echo "Error during app setup" && exit 1 || exit 0
- name: PHPUnit

View File

@@ -1,146 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: PHPUnit PostgreSQL
on:
pull_request:
schedule:
- cron: "5 2 * * *"
permissions:
contents: read
concurrency:
group: phpunit-pgsql-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src }}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '3rdparty/**'
- '**/appinfo/**'
- '**/lib/**'
- '**/templates/**'
- '**/tests/**'
- 'vendor/**'
- 'vendor-bin/**'
- '.php-cs-fixer.dist.php'
- 'composer.json'
- 'composer.lock'
- '**.php'
phpunit-pgsql:
runs-on: ubuntu-latest
needs: changes
if: needs.changes.outputs.src != 'false'
strategy:
matrix:
php-versions: ['8.1']
# To keep the matrix smaller we ignore PostgreSQL '13', '14', and '15' as we already test 12 and 16 as lower and upper bound
postgres-versions: ['12', '16']
include:
- php-versions: '8.3'
postgres-versions: '16'
coverage: ${{ github.event_name != 'pull_request' }}
name: PostgreSQL ${{ matrix.postgres-versions }} (PHP ${{ matrix.php-versions }}) - database tests
services:
cache:
image: ghcr.io/nextcloud/continuous-integration-redis:latest
ports:
- 6379:6379/tcp
options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3
postgres:
image: ghcr.io/nextcloud/continuous-integration-postgres-${{ matrix.postgres-versions }}:latest
ports:
- 4444:5432/tcp
env:
POSTGRES_USER: root
POSTGRES_PASSWORD: rootpassword
POSTGRES_DB: nextcloud
options: --mount type=tmpfs,destination=/var/lib/postgresql/data --health-cmd pg_isready --health-interval 5s --health-timeout 2s --health-retries 5
steps:
- name: Checkout server
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: ${{ matrix.php-versions }}
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, redis, session, simplexml, xmlreader, xmlwriter, zip, zlib, pgsql, pdo_pgsql
coverage: ${{ matrix.coverage && 'xdebug' || 'none' }}
ini-file: development
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up dependencies
run: composer i
- name: Set up Nextcloud
env:
DB_PORT: 4444
run: |
mkdir data
cp tests/redis.config.php config/
cp tests/preseed-config.php config/config.php
./occ maintenance:install --verbose --database=pgsql --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin
php -f tests/enable_all.php | grep -i -C9999 error && echo "Error during app setup" && exit 1 || exit 0
- name: PHPUnit database tests
run: composer run test:db ${{ matrix.coverage && ' -- --coverage-clover ./clover.db.xml' || '' }}
- name: Upload db code coverage
if: ${{ !cancelled() && matrix.coverage }}
uses: codecov/codecov-action@v4.1.1
with:
files: ./clover.db.xml
flags: phpunit-postgres
- name: Run repair steps
run: |
./occ maintenance:repair --include-expensive
- name: Print logs
if: always()
run: |
cat data/nextcloud.log
summary:
permissions:
contents: none
runs-on: ubuntu-latest-low
needs: [changes, phpunit-pgsql]
if: always()
name: phpunit-pgsql-summary
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.phpunit-pgsql.result != 'success' }}; then exit 1; fi

View File

@@ -1,130 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: PHPUnit SQLite
on:
pull_request:
schedule:
- cron: "5 2 * * *"
permissions:
contents: read
concurrency:
group: phpunit-sqlite-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src }}
steps:
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: changes
continue-on-error: true
with:
filters: |
src:
- '.github/workflows/**'
- '3rdparty/**'
- '**/appinfo/**'
- '**/lib/**'
- '**/templates/**'
- '**/tests/**'
- 'vendor/**'
- 'vendor-bin/**'
- '.php-cs-fixer.dist.php'
- 'composer.json'
- 'composer.lock'
- '**.php'
phpunit-sqlite:
runs-on: ubuntu-latest
needs: changes
if: needs.changes.outputs.src != 'false'
strategy:
matrix:
php-versions: ['8.1', '8.2', '8.3']
include:
- php-versions: '8.1'
coverage: ${{ github.event_name != 'pull_request' }}
name: SQLite (PHP ${{ matrix.php-versions }})
services:
cache:
image: ghcr.io/nextcloud/continuous-integration-redis:latest
ports:
- 6379:6379/tcp
options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3
steps:
- name: Checkout server
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: ${{ matrix.php-versions }}
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, redis, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
coverage: ${{ matrix.coverage && 'xdebug' || 'none' }}
ini-file: development
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up dependencies
run: composer i
- name: Set up Nextcloud
run: |
mkdir data
cp tests/redis.config.php config/
cp tests/preseed-config.php config/config.php
./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin
php -f tests/enable_all.php | grep -i -C9999 error && echo "Error during app setup" && exit 1 || exit 0
- name: Nextcloud debug information
run: ./occ app:list && echo "======= System config =======" && ./occ config:list system
- name: PHPUnit database tests
run: composer run test:db ${{ matrix.coverage && ' -- --coverage-clover ./clover.db.xml' || '' }}
- name: Upload db code coverage
if: ${{ !cancelled() && matrix.coverage }}
uses: codecov/codecov-action@v4.1.1
with:
files: ./clover.db.xml
flags: phpunit-sqlite
- name: Print logs
if: always()
run: |
cat data/nextcloud.log
summary:
permissions:
contents: none
runs-on: ubuntu-latest-low
needs: [changes, phpunit-sqlite]
if: always()
name: phpunit-sqlite-summary
steps:
- name: Summary status
run: if ${{ needs.changes.outputs.src != 'false' && needs.phpunit-sqlite.result != 'success' }}; then exit 1; fi

View File

@@ -1,50 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
# SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-FileCopyrightText: 2023 Marcel Klehr <mklehr@gmx.net>
# SPDX-FileCopyrightText: 2023 Joas Schilling <213943+nickvergessen@users.noreply.github.com>
# SPDX-FileCopyrightText: 2023 Daniel Kesselberg <mail@danielkesselberg.de>
# SPDX-FileCopyrightText: 2023 Florian Steffens <florian.steffens@nextcloud.com>
# SPDX-License-Identifier: MIT
name: 'Ask for feedback on PRs'
on:
schedule:
- cron: '30 1 * * *'
jobs:
pr-feedback:
runs-on: ubuntu-latest
steps:
- name: The get-github-handles-from-website action
uses: marcelklehr/get-github-handles-from-website-action@a739600f6b91da4957f51db0792697afbb2f143c # v1.0.0
id: scrape
with:
website: 'https://nextcloud.com/team/'
- name: Get blocklist
id: blocklist
run: |
blocklist=$(curl https://raw.githubusercontent.com/nextcloud/.github/master/non-community-usernames.txt | paste -s -d, -)
echo "blocklist=$blocklist" >> "$GITHUB_OUTPUT"
- uses: marcelklehr/pr-feedback-action@1883b38a033fb16f576875e0cf45f98b857655c4
with:
feedback-message: |
Hello there,
Thank you so much for taking the time and effort to create a pull request to our Nextcloud project.
We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process.
Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6
Thank you for contributing to Nextcloud and we hope to hear from you soon!
(If you believe you should not receive this message, you can add yourself to the [blocklist](https://github.com/nextcloud/.github/blob/master/non-community-usernames.txt).)
days-before-feedback: 14
start-date: '2024-04-30'
exempt-authors: '${{ steps.blocklist.outputs.blocklist }},${{ steps.scrape.outputs.users }},nextcloud-command,nextcloud-android-bot'
exempt-bots: true

View File

@@ -1,20 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
# SPDX-FileCopyrightText: 2022 Free Software Foundation Europe e.V. <https://fsfe.org>
#
# SPDX-License-Identifier: CC0-1.0
name: REUSE Compliance Check
on: pull_request
jobs:
reuse-compliance-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: REUSE Compliance Check
uses: fsfe/reuse-action@a46482ca367aef4454a87620aa37c2be4b2f8106 # v3.0.0

View File

@@ -1,35 +0,0 @@
# SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Close stale issues
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * *"
jobs:
stale:
runs-on: ubuntu-latest
if: ${{ github.repository_owner != 'nextcloud-gmbh' }}
permissions:
issues: write
steps:
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.COMMAND_BOT_PAT }}
stale-issue-message: >
This issue has been automatically marked as stale because it has not had
recent activity and seems to be missing some essential information.
It will be closed if no further activity occurs. Thank you
for your contributions.
stale-issue-label: 'stale'
only-labels: 'needs info'
labels-to-remove-when-unstale: 'needs info,stale'
exempt-issue-labels: '1. to develop,2. developing,3. to review,4. to release,security'
days-before-stale: 30
days-before-close: 14
# debug-only: true

View File

@@ -1,103 +0,0 @@
# SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Psalm static code analysis
on:
pull_request:
concurrency:
group: static-code-analysis-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
static-code-analysis:
runs-on: ubuntu-latest
if: ${{ github.repository_owner != 'nextcloud-gmbh' }}
steps:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
submodules: true
- name: Set up php
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: '8.1'
extensions: apcu,ctype,curl,dom,fileinfo,ftp,gd,intl,json,ldap,mbstring,openssl,pdo_sqlite,posix,sqlite,xml,zip
coverage: none
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Composer install
run: composer i
- name: Psalm
run: composer run psalm:ci -- --monochrome --no-progress --output-format=github --update-baseline --report=results.sarif
- name: Show potential changes in Psalm baseline
if: always()
run: git diff -- . ':!lib/composer'
- name: Upload Analysis results to GitHub
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
static-code-analysis-security:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
submodules: true
- name: Set up php
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: '8.1'
extensions: ctype,curl,dom,fileinfo,ftp,gd,intl,json,ldap,mbstring,openssl,pdo_sqlite,posix,sqlite,xml,zip
coverage: none
- name: Composer install
run: composer i
- name: Psalm taint analysis
run: composer run psalm:ci -- --monochrome --no-progress --output-format=github --report=results.sarif --taint-analysis
- name: Upload Security Analysis results to GitHub
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
static-code-analysis-ocp:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
submodules: true
- name: Set up php
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: '8.1'
extensions: ctype,curl,dom,fileinfo,gd,intl,json,mbstring,openssl,pdo_sqlite,posix,sqlite,xml,zip
coverage: none
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Composer install
run: composer i
- name: Psalm
run: composer run psalm:ci -- -c psalm-ocp.xml --monochrome --no-progress --output-format=github --update-baseline
- name: Show potential changes in Psalm baseline
if: always()
run: git diff -- . ':!lib/composer'

View File

@@ -1,45 +0,0 @@
# SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Update CA certificate bundle
on:
workflow_dispatch:
schedule:
- cron: "5 2 * * *"
jobs:
update-ca-certificate-bundle:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
branches: ['master', 'stable29', 'stable28', 'stable27', 'stable26', 'stable25', 'stable24', 'stable23', 'stable22']
name: update-ca-certificate-bundle-${{ matrix.branches }}
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
ref: ${{ matrix.branches }}
submodules: true
- name: Download CA certificate bundle from curl
run: curl --etag-compare build/ca-bundle-etag.txt --etag-save build/ca-bundle-etag.txt --output resources/config/ca-bundle.crt https://curl.se/ca/cacert.pem
- name: Create Pull Request
uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
commit-message: 'fix(security): Update CA certificate bundle'
committer: GitHub <noreply@github.com>
author: nextcloud-command <nextcloud-command@users.noreply.github.com>
signoff: true
branch: 'automated/noid/${{ matrix.branches }}-update-ca-cert-bundle'
title: '[${{ matrix.branches }}] fix(security): Update CA certificate bundle'
body: |
Auto-generated update of CA certificate bundle from [https://curl.se/docs/caextract.html](https://curl.se/docs/caextract.html)
labels: |
dependencies
3. to review
reviewers: ChristophWurst, miaulalala, nickvergessen

View File

@@ -1,48 +0,0 @@
# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Update code signing revocation list
on:
workflow_dispatch:
schedule:
- cron: "5 2 * * *"
jobs:
update-code-signing-crl:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
branches: ['master', 'stable29', 'stable28', 'stable27', 'stable26', 'stable25', 'stable24', 'stable23', 'stable22']
name: update-code-signing-crl-${{ matrix.branches }}
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
ref: ${{ matrix.branches }}
submodules: true
- name: Download CRL file from Appstore repository
run: curl --output resources/codesigning/root.crl https://raw.githubusercontent.com/nextcloud/appstore/master/nextcloudappstore/certificate/nextcloud.crl
- name: Verify CRL is from CRT
run: openssl crl -verify -in resources/codesigning/root.crl -CAfile resources/codesigning/root.crt -noout
- name: Create Pull Request
uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
commit-message: 'fix(security): Update code signing revocation list'
committer: GitHub <noreply@github.com>
author: nextcloud-command <nextcloud-command@users.noreply.github.com>
signoff: true
branch: 'automated/noid/${{ matrix.branches }}-update-code-signing-crl'
title: '[${{ matrix.branches }}] fix(security): Update code signing revocation list'
body: |
Auto-generated update of code signing revocation list from [Appstore](https://github.com/nextcloud/appstore/commits/master/nextcloudappstore/certificate/nextcloud.crl)
labels: |
dependencies
3. to review
reviewers: mgallien, miaulalala, nickvergessen

View File

@@ -1,69 +0,0 @@
# SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Update Psalm baseline
on:
workflow_dispatch:
schedule:
- cron: "5 2 * * *"
jobs:
update-psalm-baseline:
runs-on: ubuntu-latest
if: ${{ github.repository_owner != 'nextcloud-gmbh' }}
strategy:
fail-fast: false
matrix:
branches: ['master', 'stable29', 'stable28', 'stable27']
name: update-psalm-baseline-${{ matrix.branches }}
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
ref: ${{ matrix.branches }}
submodules: true
- name: Set up php
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b #v2.31.0
with:
php-version: '8.1'
extensions: apcu,ctype,curl,dom,fileinfo,ftp,gd,intl,json,ldap,mbstring,openssl,pdo_sqlite,posix,sqlite,xml,zip
coverage: none
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Composer install
run: composer install
- name: Psalm
run: composer run psalm:ci -- --monochrome --no-progress --output-format=text --update-baseline
continue-on-error: true
- name: Psalm OCP
run: composer run psalm:ci -- -c psalm-ocp.xml --monochrome --no-progress --output-format=github --update-baseline
continue-on-error: true
- name: Reset composer
run: |
git clean -f lib/composer
git checkout composer.json composer.lock lib/composer
- name: Create Pull Request
uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
commit-message: 'chore(tests): Update psalm baseline'
committer: GitHub <noreply@github.com>
author: nextcloud-command <nextcloud-command@users.noreply.github.com>
signoff: true
branch: 'automated/noid/${{ matrix.branches }}-update-psalm-baseline'
title: '[${{ matrix.branches }}] Update psalm-baseline.xml'
body: |
Auto-generated update psalm-baseline.xml with fixed psalm warnings
labels: |
automated pr
3. to review
team-reviewers: server-backend

View File

@@ -29,24 +29,24 @@ class CardSearchDao {
$cardQuery = $this->db->getQueryBuilder();
$propQuery = $this->db->getQueryBuilder();
$propOr = $propQuery->expr()->orX();
$additionalWheres = [];
if ($uid !== null) {
$propOr->add($propQuery->expr()->andX(
$additionalWheres[] = $propQuery->expr()->andX(
$propQuery->expr()->eq('name', $cardQuery->createNamedParameter('UID')),
$propQuery->expr()->eq('value', $cardQuery->createNamedParameter($uid))
));
);
}
if ($email !== null) {
$propOr->add($propQuery->expr()->andX(
$additionalWheres[] = $propQuery->expr()->andX(
$propQuery->expr()->eq('name', $cardQuery->createNamedParameter('EMAIL')),
$propQuery->expr()->eq('value', $cardQuery->createNamedParameter($email))
));
);
}
if ($cloudId !== null) {
$propOr->add($propQuery->expr()->andX(
$additionalWheres[] = $propQuery->expr()->andX(
$propQuery->expr()->eq('name', $cardQuery->createNamedParameter('CLOUD')),
$propQuery->expr()->eq('value', $cardQuery->createNamedParameter($cloudId))
));
);
}
$addressbooksQuery->selectDistinct('id')
->from('addressbooks')
@@ -54,8 +54,12 @@ class CardSearchDao {
$propQuery->selectDistinct('cardid')
->from('cards_properties')
->where($propQuery->expr()->in('addressbookid', $propQuery->createFunction($addressbooksQuery->getSQL()), IQueryBuilder::PARAM_INT_ARRAY))
->andWhere($propOr)
->groupBy('cardid');
if (!empty($additionalWheres)) {
$propQuery->andWhere($propQuery->expr()->orX(...$additionalWheres));
}
$cardQuery->select('carddata')
->from('cards')
->where($cardQuery->expr()->in('id', $cardQuery->createFunction($propQuery->getSQL()), IQueryBuilder::PARAM_INT_ARRAY))

View File

@@ -61,23 +61,25 @@ class RecentContactMapper extends QBMapper {
?string $cloudId): array {
$qb = $this->db->getQueryBuilder();
$or = $qb->expr()->orX();
$additionalWheres = [];
if ($uid !== null) {
$or->add($qb->expr()->eq('uid', $qb->createNamedParameter($uid)));
$additionalWheres[] = $qb->expr()->eq('uid', $qb->createNamedParameter($uid));
}
if ($email !== null) {
$or->add($qb->expr()->eq('email', $qb->createNamedParameter($email)));
$additionalWheres[] = $qb->expr()->eq('email', $qb->createNamedParameter($email));
}
if ($cloudId !== null) {
$or->add($qb->expr()->eq('federated_cloud_id', $qb->createNamedParameter($cloudId)));
$additionalWheres[] = $qb->expr()->eq('federated_cloud_id', $qb->createNamedParameter($cloudId));
}
$select = $qb
->select('*')
->from($this->getTableName())
->where($or)
->andWhere($qb->expr()->eq('actor_uid', $qb->createNamedParameter($user->getUID())));
->where($qb->expr()->eq('actor_uid', $qb->createNamedParameter($user->getUID())));
if (!empty($additionalWheres)) {
$select->andWhere($select->expr()->orX(...$additionalWheres));
}
return $this->findEntities($select);
}

View File

@@ -1874,12 +1874,12 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
}
if (!empty($searchProperties)) {
$or = $innerQuery->expr()->orX();
$or = [];
foreach ($searchProperties as $searchProperty) {
$or->add($innerQuery->expr()->eq('op.name',
$outerQuery->createNamedParameter($searchProperty)));
$or[] = $innerQuery->expr()->eq('op.name',
$outerQuery->createNamedParameter($searchProperty));
}
$innerQuery->andWhere($or);
$innerQuery->andWhere($innerQuery->expr()->orX(...$or));
}
if ($pattern !== '') {
@@ -1923,12 +1923,12 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
}
if (!empty($options['types'])) {
$or = $outerQuery->expr()->orX();
$or = [];
foreach ($options['types'] as $type) {
$or->add($outerQuery->expr()->eq('componenttype',
$outerQuery->createNamedParameter($type)));
$or[] = $outerQuery->expr()->eq('componenttype',
$outerQuery->createNamedParameter($type));
}
$outerQuery->andWhere($or);
$outerQuery->andWhere($outerQuery->expr()->orX(...$or));
}
$outerQuery->andWhere($outerQuery->expr()->in('c.id', $outerQuery->createFunction($innerQuery->getSQL())));
@@ -2149,16 +2149,17 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$escapePattern = !\array_key_exists('escape_like_param', $options) || $options['escape_like_param'] !== false;
$calendarObjectIdQuery = $this->db->getQueryBuilder();
$calendarOr = $calendarObjectIdQuery->expr()->orX();
$searchOr = $calendarObjectIdQuery->expr()->orX();
$calendarOr = [];
$searchOr = [];
// Fetch calendars and subscription
$calendars = $this->getCalendarsForUser($principalUri);
$subscriptions = $this->getSubscriptionsForUser($principalUri);
foreach ($calendars as $calendar) {
$calendarAnd = $calendarObjectIdQuery->expr()->andX();
$calendarAnd->add($calendarObjectIdQuery->expr()->eq('cob.calendarid', $calendarObjectIdQuery->createNamedParameter((int)$calendar['id'])));
$calendarAnd->add($calendarObjectIdQuery->expr()->eq('cob.calendartype', $calendarObjectIdQuery->createNamedParameter(self::CALENDAR_TYPE_CALENDAR)));
$calendarAnd = $calendarObjectIdQuery->expr()->andX(
$calendarObjectIdQuery->expr()->eq('cob.calendarid', $calendarObjectIdQuery->createNamedParameter((int)$calendar['id'])),
$calendarObjectIdQuery->expr()->eq('cob.calendartype', $calendarObjectIdQuery->createNamedParameter(self::CALENDAR_TYPE_CALENDAR)),
);
// If it's shared, limit search to public events
if (isset($calendar['{http://owncloud.org/ns}owner-principal'])
@@ -2166,12 +2167,13 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$calendarAnd->add($calendarObjectIdQuery->expr()->eq('co.classification', $calendarObjectIdQuery->createNamedParameter(self::CLASSIFICATION_PUBLIC)));
}
$calendarOr->add($calendarAnd);
$calendarOr[] = $calendarAnd;
}
foreach ($subscriptions as $subscription) {
$subscriptionAnd = $calendarObjectIdQuery->expr()->andX();
$subscriptionAnd->add($calendarObjectIdQuery->expr()->eq('cob.calendarid', $calendarObjectIdQuery->createNamedParameter((int)$subscription['id'])));
$subscriptionAnd->add($calendarObjectIdQuery->expr()->eq('cob.calendartype', $calendarObjectIdQuery->createNamedParameter(self::CALENDAR_TYPE_SUBSCRIPTION)));
$subscriptionAnd = $calendarObjectIdQuery->expr()->andX(
$calendarObjectIdQuery->expr()->eq('cob.calendarid', $calendarObjectIdQuery->createNamedParameter((int)$subscription['id'])),
$calendarObjectIdQuery->expr()->eq('cob.calendartype', $calendarObjectIdQuery->createNamedParameter(self::CALENDAR_TYPE_SUBSCRIPTION)),
);
// If it's shared, limit search to public events
if (isset($subscription['{http://owncloud.org/ns}owner-principal'])
@@ -2179,28 +2181,30 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$subscriptionAnd->add($calendarObjectIdQuery->expr()->eq('co.classification', $calendarObjectIdQuery->createNamedParameter(self::CLASSIFICATION_PUBLIC)));
}
$calendarOr->add($subscriptionAnd);
$calendarOr[] = $subscriptionAnd;
}
foreach ($searchProperties as $property) {
$propertyAnd = $calendarObjectIdQuery->expr()->andX();
$propertyAnd->add($calendarObjectIdQuery->expr()->eq('cob.name', $calendarObjectIdQuery->createNamedParameter($property, IQueryBuilder::PARAM_STR)));
$propertyAnd->add($calendarObjectIdQuery->expr()->isNull('cob.parameter'));
$propertyAnd = $calendarObjectIdQuery->expr()->andX(
$calendarObjectIdQuery->expr()->eq('cob.name', $calendarObjectIdQuery->createNamedParameter($property, IQueryBuilder::PARAM_STR)),
$calendarObjectIdQuery->expr()->isNull('cob.parameter'),
);
$searchOr->add($propertyAnd);
$searchOr[] = $propertyAnd;
}
foreach ($searchParameters as $property => $parameter) {
$parameterAnd = $calendarObjectIdQuery->expr()->andX();
$parameterAnd->add($calendarObjectIdQuery->expr()->eq('cob.name', $calendarObjectIdQuery->createNamedParameter($property, IQueryBuilder::PARAM_STR)));
$parameterAnd->add($calendarObjectIdQuery->expr()->eq('cob.parameter', $calendarObjectIdQuery->createNamedParameter($parameter, IQueryBuilder::PARAM_STR_ARRAY)));
$parameterAnd = $calendarObjectIdQuery->expr()->andX(
$calendarObjectIdQuery->expr()->eq('cob.name', $calendarObjectIdQuery->createNamedParameter($property, IQueryBuilder::PARAM_STR)),
$calendarObjectIdQuery->expr()->eq('cob.parameter', $calendarObjectIdQuery->createNamedParameter($parameter, IQueryBuilder::PARAM_STR_ARRAY)),
);
$searchOr->add($parameterAnd);
$searchOr[] = $parameterAnd;
}
if ($calendarOr->count() === 0) {
if (empty($calendarOr)) {
return [];
}
if ($searchOr->count() === 0) {
if (empty($searchOr)) {
return [];
}
@@ -2208,8 +2212,8 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
->from($this->dbObjectPropertiesTable, 'cob')
->leftJoin('cob', 'calendarobjects', 'co', $calendarObjectIdQuery->expr()->eq('co.id', 'cob.objectid'))
->andWhere($calendarObjectIdQuery->expr()->in('co.componenttype', $calendarObjectIdQuery->createNamedParameter($componentTypes, IQueryBuilder::PARAM_STR_ARRAY)))
->andWhere($calendarOr)
->andWhere($searchOr)
->andWhere($calendarObjectIdQuery->expr()->orX(...$calendarOr))
->andWhere($calendarObjectIdQuery->expr()->orX(...$searchOr))
->andWhere($calendarObjectIdQuery->expr()->isNull('deleted_at'));
if ($pattern !== '') {

View File

@@ -1148,20 +1148,20 @@ class CardDavBackend implements BackendInterface, SyncSupport {
/**
* FIXME Find a way to match only 4 last digits
* BDAY can be --1018 without year or 20001019 with it
* $bDayOr = $query2->expr()->orX();
* $bDayOr = [];
* if ($options['since'] instanceof DateTimeFilter) {
* $bDayOr->add(
* $bDayOr[] =
* $query2->expr()->gte('SUBSTR(cp_bday.value, -4)',
* $query2->createNamedParameter($options['since']->get()->format('md')))
* $query2->createNamedParameter($options['since']->get()->format('md'))
* );
* }
* if ($options['until'] instanceof DateTimeFilter) {
* $bDayOr->add(
* $bDayOr[] =
* $query2->expr()->lte('SUBSTR(cp_bday.value, -4)',
* $query2->createNamedParameter($options['until']->get()->format('md')))
* $query2->createNamedParameter($options['until']->get()->format('md'))
* );
* }
* $query2->andWhere($bDayOr);
* $query2->andWhere($query2->expr()->orX(...$bDayOr));
*/
}

View File

@@ -411,7 +411,7 @@ class CustomPropertiesBackend implements BackendInterface {
// request only a subset
$sql .= ' AND `propertyname` in (?)';
$whereValues[] = $requestedProperties;
$whereTypes[] = \Doctrine\DBAL\Connection::PARAM_STR_ARRAY;
$whereTypes[] = IQueryBuilder::PARAM_STR_ARRAY;
}
$result = $this->connection->executeQuery(

View File

@@ -5,7 +5,6 @@
*/
namespace OCA\DAV\Migration;
use Doctrine\DBAL\Platforms\OraclePlatform;
use OCA\DAV\CalDAV\CalDavBackend;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
@@ -75,7 +74,7 @@ class CalDAVRemoveEmptyValue implements IRepairStep {
}
protected function getInvalidObjects($pattern) {
if ($this->db->getDatabasePlatform() instanceof OraclePlatform) {
if ($this->db->getDatabaseProvider() === IDBConnection::PLATFORM_ORACLE) {
$rows = [];
$chunkSize = 500;
$query = $this->db->getQueryBuilder();

View File

@@ -233,7 +233,7 @@ class Version1004Date20170825134824 extends SimpleMigrationStep {
$table->addUniqueIndex(['principaluri', 'uri'], 'calendars_index');
} else {
$table = $schema->getTable('calendars');
$table->changeColumn('components', [
$table->modifyColumn('components', [
'notnull' => false,
'length' => 64,
]);
@@ -323,7 +323,7 @@ class Version1004Date20170825134824 extends SimpleMigrationStep {
$table->addUniqueIndex(['principaluri', 'uri'], 'calsub_index');
} else {
$table = $schema->getTable('calendarsubscriptions');
$table->changeColumn('lastmodified', [
$table->modifyColumn('lastmodified', [
'notnull' => false,
'unsigned' => true,
]);

View File

@@ -32,7 +32,7 @@ class Version1011Date20201120125158 extends SimpleMigrationStep {
if ($schema->hasTable('federated_reshares')) {
$table = $schema->getTable('federated_reshares');
$remoteIdColumn = $table->getColumn('remote_id');
if ($remoteIdColumn && $remoteIdColumn->getType()->getName() !== Types::STRING) {
if (Types::getType($remoteIdColumn->getType()) !== Types::STRING) {
$remoteIdColumn->setNotnull(false);
$remoteIdColumn->setType(Type::getType(Types::STRING));
$remoteIdColumn->setOptions(['length' => 255]);

View File

@@ -103,7 +103,7 @@ class Version1011Date20200630192246 extends SimpleMigrationStep {
$table->addUniqueIndex(['mount_id', 'key'], 'config_mount_key');
} else {
$table = $schema->getTable('external_config');
$table->changeColumn('value', [
$table->modifyColumn('value', [
'notnull' => false,
'length' => 4000,
]);

View File

@@ -90,7 +90,7 @@ class Version11300Date20201120141438 extends SimpleMigrationStep {
} else {
$table = $schema->getTable('share_external');
$remoteIdColumn = $table->getColumn('remote_id');
if ($remoteIdColumn && $remoteIdColumn->getType()->getName() !== Types::STRING) {
if (Types::getType($remoteIdColumn->getType()) !== Types::STRING) {
$remoteIdColumn->setNotnull(false);
$remoteIdColumn->setType(Type::getType(Types::STRING));
$remoteIdColumn->setOptions(['length' => 255]);

View File

@@ -11,7 +11,7 @@ namespace OCA\Settings\SetupChecks;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Platforms\OraclePlatform;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Platforms\SQLitePlatform;
use OCP\IDBConnection;
use OCP\IL10N;
use OCP\IURLGenerator;
@@ -103,7 +103,7 @@ class SupportedDatabase implements ISetupCheck {
}
} elseif ($databasePlatform instanceof OraclePlatform) {
$version = 'Oracle';
} elseif ($databasePlatform instanceof SqlitePlatform) {
} elseif ($databasePlatform instanceof SQLitePlatform) {
return SetupResult::warning(
$this->l10n->t('SQLite is currently being used as the backend database. For larger installations we recommend that you switch to a different database backend. This is particularly recommended when using the desktop client for file synchronisation. To migrate to another database use the command line tool: "occ db:convert-type".'),
$this->urlGenerator->linkToDocs('admin-db-conversion')

View File

@@ -8,7 +8,6 @@ declare(strict_types=1);
*/
namespace OCA\Settings\Tests;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use OCA\Settings\SetupChecks\SupportedDatabase;
use OCP\IDBConnection;
use OCP\IL10N;
@@ -41,8 +40,7 @@ class SupportedDatabaseTest extends TestCase {
}
public function testPass(): void {
$platform = $this->connection->getDatabasePlatform();
if ($platform instanceof SqlitePlatform) {
if ($this->connection->getDatabaseProvider() === IDBConnection::PLATFORM_SQLITE) {
/** SQlite always gets a warning */
$this->assertEquals(SetupResult::WARNING, $this->check->run()->getSeverity());
} else {

View File

@@ -9,8 +9,8 @@ declare(strict_types=1);
namespace OCA\TwoFactorBackupCodes\Migration;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Types\Types;
use OCP\DB\ISchemaWrapper;
use OCP\DB\Types;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;
@@ -32,7 +32,7 @@ class Version1002Date20170919123342 extends SimpleMigrationStep {
$column->setDefault('');
$column = $table->getColumn('used');
if ($column->getType()->getName() !== Types::SMALLINT) {
if (Types::getType($column->getType()) !== Types::SMALLINT) {
$column->setType(Type::getType(Types::SMALLINT));
$column->setOptions(['length' => 6]);
}

View File

@@ -8,9 +8,9 @@
namespace OCA\User_LDAP\Mapping;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use OCP\DB\IPreparedStatement;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
use Psr\Log\LoggerInterface;
/**
@@ -202,7 +202,7 @@ abstract class AbstractMapping {
protected function collectResultsFromListOfIdsQuery(IQueryBuilder $qb, array &$results): void {
$stmt = $qb->executeQuery();
while ($entry = $stmt->fetch(\Doctrine\DBAL\FetchMode::ASSOCIATIVE)) {
while ($entry = $stmt->fetch()) {
$results[$entry['ldap_dn']] = $entry['owncloud_name'];
$this->cache[$entry['ldap_dn']] = $entry['owncloud_name'];
}
@@ -216,7 +216,7 @@ abstract class AbstractMapping {
public function getListOfIdsByDn(array $fdns): array {
$totalDBParamLimit = 65000;
$sliceSize = 1000;
$maxSlices = $this->dbc->getDatabasePlatform() instanceof SqlitePlatform ? 9 : $totalDBParamLimit / $sliceSize;
$maxSlices = $this->dbc->getDatabaseProvider() === IDBConnection::PLATFORM_SQLITE ? 9 : $totalDBParamLimit / $sliceSize;
$results = [];
$slice = 1;

View File

@@ -27,7 +27,7 @@ class Version2200Date20210805101925 extends SimpleMigrationStep {
if ($schema->hasTable('flow_operations')) {
$table = $schema->getTable('flow_operations');
$table->changeColumn('name', [
$table->modifyColumn('name', [
'notnull' => false,
]);
}

View File

@@ -55,7 +55,7 @@ class AddMissingPrimaryKeys extends Command {
foreach ($missingKeys as $missingKey) {
if ($schema->hasTable($missingKey['tableName'])) {
$table = $schema->getTable($missingKey['tableName']);
if (!$table->hasPrimaryKey()) {
if (!$table->getPrimaryKey()) {
$output->writeln('<info>Adding primary key to the ' . $missingKey['tableName'] . ' table, this can take some time...</info>');
$table->setPrimaryKey($missingKey['columns'], $missingKey['primaryKeyName']);

View File

@@ -5,11 +5,11 @@
*/
namespace OC\Core\Command\Db;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Types\Type;
use OC\DB\Connection;
use OC\DB\SchemaWrapper;
use OCP\DB\Types;
use OCP\IDBConnection;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@@ -53,7 +53,7 @@ class ConvertFilecacheBigInt extends Command {
protected function execute(InputInterface $input, OutputInterface $output): int {
$schema = new SchemaWrapper($this->connection);
$isSqlite = $this->connection->getDatabasePlatform() instanceof SqlitePlatform;
$isSqlite = $this->connection->getDatabaseProvider() === IDBConnection::PLATFORM_SQLITE;
$updates = [];
$tables = static::getColumnsByTable();
@@ -68,7 +68,7 @@ class ConvertFilecacheBigInt extends Command {
$column = $table->getColumn($columnName);
$isAutoIncrement = $column->getAutoincrement();
$isAutoIncrementOnSqlite = $isSqlite && $isAutoIncrement;
if ($column->getType()->getName() !== Types::BIGINT && !$isAutoIncrementOnSqlite) {
if (Types::getType($column->getType()) !== Types::BIGINT && !$isAutoIncrementOnSqlite) {
$column->setType(Type::getType(Types::BIGINT));
$column->setOptions(['length' => 20]);

View File

@@ -5,7 +5,6 @@
*/
namespace OC\Core\Command\Db;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use OC\DB\MySqlTools;
use OC\Migration\ConsoleOutput;
use OC\Repair\Collation;
@@ -34,7 +33,7 @@ class ConvertMysqlToMB4 extends Command {
}
protected function execute(InputInterface $input, OutputInterface $output): int {
if (!$this->connection->getDatabasePlatform() instanceof MySQLPlatform) {
if ($this->connection->getDatabaseProvider() !== IDBConnection::PLATFORM_MYSQL) {
$output->writeln("This command is only valid for MySQL/MariaDB databases.");
return 1;
}

View File

@@ -9,6 +9,7 @@ namespace OC\Core\Command\Db;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Schema\AbstractAsset;
use Doctrine\DBAL\Schema\Index;
use Doctrine\DBAL\Schema\Table;
use OC\DB\Connection;
use OC\DB\ConnectionFactory;
@@ -245,7 +246,7 @@ class ConvertType extends Command implements CompletionAwareInterface {
$output->writeln('<info>Clearing schema in new database</info>');
}
foreach ($toTables as $table) {
$db->getSchemaManager()->dropTable($table);
$db->createSchemaManager()->dropTable($table);
}
}
@@ -258,7 +259,7 @@ class ConvertType extends Command implements CompletionAwareInterface {
}
return preg_match($filterExpression, $asset) !== false;
});
return $db->getSchemaManager()->listTableNames();
return $db->createSchemaManager()->listTableNames();
}
/**
@@ -302,7 +303,12 @@ class ConvertType extends Command implements CompletionAwareInterface {
->setMaxResults($chunkSize);
try {
$orderColumns = $table->getPrimaryKeyColumns();
$key = $table->getPrimaryKey();
if ($key instanceof Index) {
$orderColumns = $key->getColumns();
} else {
$orderColumns = $table->getColumns();
}
} catch (Exception $e) {
$orderColumns = $table->getColumns();
}
@@ -362,7 +368,7 @@ class ConvertType extends Command implements CompletionAwareInterface {
return $this->columnTypes[$tableName][$columnName];
}
$type = $table->getColumn($columnName)->getType()->getName();
$type = Types::getType($table->getColumn($columnName)->getType());
switch ($type) {
case Types::BLOB:

View File

@@ -5,7 +5,6 @@
*/
namespace OC\Core\Migrations;
use Doctrine\DBAL\Platforms\PostgreSQL94Platform;
use OCP\DB\ISchemaWrapper;
use OCP\DB\Types;
use OCP\IDBConnection;
@@ -238,7 +237,7 @@ class Version13000Date20170718121200 extends SimpleMigrationStep {
$table->addIndex(['name'], 'fs_name_hash');
$table->addIndex(['mtime'], 'fs_mtime');
$table->addIndex(['size'], 'fs_size');
if (!$schema->getDatabasePlatform() instanceof PostgreSQL94Platform) {
if ($this->connection->getDatabaseProvider() !== IDBConnection::PLATFORM_POSTGRES) {
$table->addIndex(['storage', 'path'], 'fs_storage_path_prefix', [], ['lengths' => [null, 64]]);
}
}

View File

@@ -24,16 +24,16 @@ class Version21000Date20201120141228 extends SimpleMigrationStep {
if ($loginNameColumn->getLength() !== 255) {
$loginNameColumn->setLength(255);
}
$table->changeColumn('type', [
$table->modifyColumn('type', [
'notnull' => false,
]);
$table->changeColumn('remember', [
$table->modifyColumn('remember', [
'notnull' => false,
]);
$table->changeColumn('last_activity', [
$table->modifyColumn('last_activity', [
'notnull' => false,
]);
$table->changeColumn('last_check', [
$table->modifyColumn('last_check', [
'notnull' => false,
]);
}
@@ -51,7 +51,7 @@ class Version21000Date20201120141228 extends SimpleMigrationStep {
if ($schema->hasTable('jobs')) {
$table = $schema->getTable('jobs');
$table->changeColumn('execution_duration', [
$table->modifyColumn('execution_duration', [
'notnull' => false,
'default' => 0,
]);

View File

@@ -1321,12 +1321,18 @@ return array(
'OC\\DB\\AdapterOCI8' => $baseDir . '/lib/private/DB/AdapterOCI8.php',
'OC\\DB\\AdapterPgSql' => $baseDir . '/lib/private/DB/AdapterPgSql.php',
'OC\\DB\\AdapterSqlite' => $baseDir . '/lib/private/DB/AdapterSqlite.php',
'OC\\DB\\BacktraceDebugStack' => $baseDir . '/lib/private/DB/BacktraceDebugStack.php',
'OC\\DB\\Connection' => $baseDir . '/lib/private/DB/Connection.php',
'OC\\DB\\ConnectionAdapter' => $baseDir . '/lib/private/DB/ConnectionAdapter.php',
'OC\\DB\\ConnectionFactory' => $baseDir . '/lib/private/DB/ConnectionFactory.php',
'OC\\DB\\DbDataCollector' => $baseDir . '/lib/private/DB/DbDataCollector.php',
'OC\\DB\\Exceptions\\DbalException' => $baseDir . '/lib/private/DB/Exceptions/DbalException.php',
'OC\\DB\\Logging\\Connection' => $baseDir . '/lib/private/DB/Logging/Connection.php',
'OC\\DB\\Logging\\Driver' => $baseDir . '/lib/private/DB/Logging/Driver.php',
'OC\\DB\\Logging\\Middleware' => $baseDir . '/lib/private/DB/Logging/Middleware.php',
'OC\\DB\\Logging\\Statement' => $baseDir . '/lib/private/DB/Logging/Statement.php',
'OC\\DB\\Middlewares\\SQLiteCaseSensitiveLike' => $baseDir . '/lib/private/DB/Middlewares/SQLiteCaseSensitiveLike.php',
'OC\\DB\\Middlewares\\SQLiteJournalMode' => $baseDir . '/lib/private/DB/Middlewares/SQLiteJournalMode.php',
'OC\\DB\\Middlewares\\SetTransactionIsolationLevel' => $baseDir . '/lib/private/DB/Middlewares/SetTransactionIsolationLevel.php',
'OC\\DB\\MigrationException' => $baseDir . '/lib/private/DB/MigrationException.php',
'OC\\DB\\MigrationService' => $baseDir . '/lib/private/DB/MigrationService.php',
'OC\\DB\\Migrator' => $baseDir . '/lib/private/DB/Migrator.php',
@@ -1335,7 +1341,6 @@ return array(
'OC\\DB\\MissingIndexInformation' => $baseDir . '/lib/private/DB/MissingIndexInformation.php',
'OC\\DB\\MissingPrimaryKeyInformation' => $baseDir . '/lib/private/DB/MissingPrimaryKeyInformation.php',
'OC\\DB\\MySqlTools' => $baseDir . '/lib/private/DB/MySqlTools.php',
'OC\\DB\\OCSqlitePlatform' => $baseDir . '/lib/private/DB/OCSqlitePlatform.php',
'OC\\DB\\ObjectParameter' => $baseDir . '/lib/private/DB/ObjectParameter.php',
'OC\\DB\\OracleConnection' => $baseDir . '/lib/private/DB/OracleConnection.php',
'OC\\DB\\OracleMigrator' => $baseDir . '/lib/private/DB/OracleMigrator.php',
@@ -1358,9 +1363,8 @@ return array(
'OC\\DB\\QueryBuilder\\QuoteHelper' => $baseDir . '/lib/private/DB/QueryBuilder/QuoteHelper.php',
'OC\\DB\\ResultAdapter' => $baseDir . '/lib/private/DB/ResultAdapter.php',
'OC\\DB\\SQLiteMigrator' => $baseDir . '/lib/private/DB/SQLiteMigrator.php',
'OC\\DB\\SQLiteSessionInit' => $baseDir . '/lib/private/DB/SQLiteSessionInit.php',
'OC\\DB\\SchemaWrapper' => $baseDir . '/lib/private/DB/SchemaWrapper.php',
'OC\\DB\\SetTransactionIsolationLevel' => $baseDir . '/lib/private/DB/SetTransactionIsolationLevel.php',
'OC\\DB\\TDoctrineParameterTypeMap' => $baseDir . '/lib/private/DB/TDoctrineParameterTypeMap.php',
'OC\\Dashboard\\Manager' => $baseDir . '/lib/private/Dashboard/Manager.php',
'OC\\DatabaseException' => $baseDir . '/lib/private/DatabaseException.php',
'OC\\DatabaseSetupException' => $baseDir . '/lib/private/DatabaseSetupException.php',

View File

@@ -1354,12 +1354,18 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\DB\\AdapterOCI8' => __DIR__ . '/../../..' . '/lib/private/DB/AdapterOCI8.php',
'OC\\DB\\AdapterPgSql' => __DIR__ . '/../../..' . '/lib/private/DB/AdapterPgSql.php',
'OC\\DB\\AdapterSqlite' => __DIR__ . '/../../..' . '/lib/private/DB/AdapterSqlite.php',
'OC\\DB\\BacktraceDebugStack' => __DIR__ . '/../../..' . '/lib/private/DB/BacktraceDebugStack.php',
'OC\\DB\\Connection' => __DIR__ . '/../../..' . '/lib/private/DB/Connection.php',
'OC\\DB\\ConnectionAdapter' => __DIR__ . '/../../..' . '/lib/private/DB/ConnectionAdapter.php',
'OC\\DB\\ConnectionFactory' => __DIR__ . '/../../..' . '/lib/private/DB/ConnectionFactory.php',
'OC\\DB\\DbDataCollector' => __DIR__ . '/../../..' . '/lib/private/DB/DbDataCollector.php',
'OC\\DB\\Exceptions\\DbalException' => __DIR__ . '/../../..' . '/lib/private/DB/Exceptions/DbalException.php',
'OC\\DB\\Logging\\Connection' => __DIR__ . '/../../..' . '/lib/private/DB/Logging/Connection.php',
'OC\\DB\\Logging\\Driver' => __DIR__ . '/../../..' . '/lib/private/DB/Logging/Driver.php',
'OC\\DB\\Logging\\Middleware' => __DIR__ . '/../../..' . '/lib/private/DB/Logging/Middleware.php',
'OC\\DB\\Logging\\Statement' => __DIR__ . '/../../..' . '/lib/private/DB/Logging/Statement.php',
'OC\\DB\\Middlewares\\SQLiteCaseSensitiveLike' => __DIR__ . '/../../..' . '/lib/private/DB/Middlewares/SQLiteCaseSensitiveLike.php',
'OC\\DB\\Middlewares\\SQLiteJournalMode' => __DIR__ . '/../../..' . '/lib/private/DB/Middlewares/SQLiteJournalMode.php',
'OC\\DB\\Middlewares\\SetTransactionIsolationLevel' => __DIR__ . '/../../..' . '/lib/private/DB/Middlewares/SetTransactionIsolationLevel.php',
'OC\\DB\\MigrationException' => __DIR__ . '/../../..' . '/lib/private/DB/MigrationException.php',
'OC\\DB\\MigrationService' => __DIR__ . '/../../..' . '/lib/private/DB/MigrationService.php',
'OC\\DB\\Migrator' => __DIR__ . '/../../..' . '/lib/private/DB/Migrator.php',
@@ -1368,7 +1374,6 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\DB\\MissingIndexInformation' => __DIR__ . '/../../..' . '/lib/private/DB/MissingIndexInformation.php',
'OC\\DB\\MissingPrimaryKeyInformation' => __DIR__ . '/../../..' . '/lib/private/DB/MissingPrimaryKeyInformation.php',
'OC\\DB\\MySqlTools' => __DIR__ . '/../../..' . '/lib/private/DB/MySqlTools.php',
'OC\\DB\\OCSqlitePlatform' => __DIR__ . '/../../..' . '/lib/private/DB/OCSqlitePlatform.php',
'OC\\DB\\ObjectParameter' => __DIR__ . '/../../..' . '/lib/private/DB/ObjectParameter.php',
'OC\\DB\\OracleConnection' => __DIR__ . '/../../..' . '/lib/private/DB/OracleConnection.php',
'OC\\DB\\OracleMigrator' => __DIR__ . '/../../..' . '/lib/private/DB/OracleMigrator.php',
@@ -1391,9 +1396,8 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\DB\\QueryBuilder\\QuoteHelper' => __DIR__ . '/../../..' . '/lib/private/DB/QueryBuilder/QuoteHelper.php',
'OC\\DB\\ResultAdapter' => __DIR__ . '/../../..' . '/lib/private/DB/ResultAdapter.php',
'OC\\DB\\SQLiteMigrator' => __DIR__ . '/../../..' . '/lib/private/DB/SQLiteMigrator.php',
'OC\\DB\\SQLiteSessionInit' => __DIR__ . '/../../..' . '/lib/private/DB/SQLiteSessionInit.php',
'OC\\DB\\SchemaWrapper' => __DIR__ . '/../../..' . '/lib/private/DB/SchemaWrapper.php',
'OC\\DB\\SetTransactionIsolationLevel' => __DIR__ . '/../../..' . '/lib/private/DB/SetTransactionIsolationLevel.php',
'OC\\DB\\TDoctrineParameterTypeMap' => __DIR__ . '/../../..' . '/lib/private/DB/TDoctrineParameterTypeMap.php',
'OC\\Dashboard\\Manager' => __DIR__ . '/../../..' . '/lib/private/Dashboard/Manager.php',
'OC\\DatabaseException' => __DIR__ . '/../../..' . '/lib/private/DatabaseException.php',
'OC\\DatabaseSetupException' => __DIR__ . '/../../..' . '/lib/private/DatabaseSetupException.php',

View File

@@ -6,7 +6,6 @@
*/
namespace OC;
use Doctrine\DBAL\Platforms\OraclePlatform;
use OCP\Cache\CappedMemoryCache;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IConfig;
@@ -470,7 +469,7 @@ class AllConfig implements IConfig {
$this->fixDIInit();
$qb = $this->connection->getQueryBuilder();
$configValueColumn = ($this->connection->getDatabasePlatform() instanceof OraclePlatform)
$configValueColumn = ($this->connection->getDatabaseProvider() === IDBConnection::PLATFORM_ORACLE)
? $qb->expr()->castColumn('configvalue', IQueryBuilder::PARAM_STR)
: 'configvalue';
$result = $qb->select('userid')
@@ -509,7 +508,7 @@ class AllConfig implements IConfig {
}
$qb = $this->connection->getQueryBuilder();
$configValueColumn = ($this->connection->getDatabasePlatform() instanceof OraclePlatform)
$configValueColumn = ($this->connection->getDatabaseProvider() === IDBConnection::PLATFORM_ORACLE)
? $qb->expr()->castColumn('configvalue', IQueryBuilder::PARAM_STR)
: 'configvalue';

View File

@@ -7,7 +7,6 @@
*/
namespace OC\BackgroundJob;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use OCP\AppFramework\QueryException;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\AutoloadNotAllowedException;
@@ -98,7 +97,7 @@ class JobList implements IJobList {
// Add galera safe delete chunking if using mysql
// Stops us hitting wsrep_max_ws_rows when large row counts are deleted
if ($this->connection->getDatabasePlatform() instanceof MySQLPlatform) {
if ($this->connection->getDatabaseProvider() === IDBConnection::PLATFORM_MYSQL) {
// Then use chunked delete
$max = IQueryBuilder::MAX_ROW_DELETION;
@@ -204,12 +203,12 @@ class JobList implements IJobList {
$query->andWhere($query->expr()->eq('time_sensitive', $query->createNamedParameter(IJob::TIME_SENSITIVE, IQueryBuilder::PARAM_INT)));
}
if ($jobClasses !== null && count($jobClasses) > 0) {
$orClasses = $query->expr()->orx();
if (!empty($jobClasses)) {
$orClasses = [];
foreach ($jobClasses as $jobClass) {
$orClasses->add($query->expr()->eq('class', $query->createNamedParameter($jobClass, IQueryBuilder::PARAM_STR)));
$orClasses[] = $query->expr()->eq('class', $query->createNamedParameter($jobClass, IQueryBuilder::PARAM_STR));
}
$query->andWhere($orClasses);
$query->andWhere($query->expr()->orX(...$orClasses));
}
$result = $query->executeQuery();

View File

@@ -26,6 +26,13 @@ class AdapterOCI8 extends Adapter {
$statement = str_replace('`', '"', $statement);
$statement = str_ireplace('NOW()', 'CURRENT_TIMESTAMP', $statement);
$statement = str_ireplace('UNIX_TIMESTAMP()', self::UNIX_TIMESTAMP_REPLACEMENT, $statement);
$statement = preg_replace(
'/^INSERT INTO (".*")( ?\(.*) ?VALUES( ?\(.*)$/',
'DECLARE vRowid ROWID; BEGIN INSERT INTO ${1} VALUES ${2}; RETURNING ROWID INTO vRowid dbms_output.put_line(vRowid); END;',
$statement
);
return $statement;
}
}

View File

@@ -1,20 +0,0 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\DB;
use Doctrine\DBAL\Logging\DebugStack;
class BacktraceDebugStack extends DebugStack {
public function startQuery($sql, ?array $params = null, ?array $types = null) {
parent::startQuery($sql, $params, $types);
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
$this->queries[$this->currentQuery]['backtrace'] = $backtrace;
$this->queries[$this->currentQuery]['start'] = $this->start;
}
}

View File

@@ -8,16 +8,18 @@ declare(strict_types=1);
*/
namespace OC\DB;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\Cache\QueryCacheProfile;
use Doctrine\DBAL\Configuration;
use Doctrine\DBAL\ConnectionException;
use Doctrine\DBAL\Connections\PrimaryReadReplicaConnection;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Exception\ConnectionLost;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Platforms\OraclePlatform;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Platforms\SQLitePlatform;
use Doctrine\DBAL\Result;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Statement;
@@ -25,6 +27,8 @@ use OC\DB\QueryBuilder\QueryBuilder;
use OC\SystemConfig;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Diagnostics\IEventLogger;
use OCP\Diagnostics\IQueryLogger;
use OCP\IDBConnection;
use OCP\IRequestId;
use OCP\PreConditionNotMetException;
use OCP\Profiler\IProfiler;
@@ -36,6 +40,8 @@ use function count;
use function in_array;
class Connection extends PrimaryReadReplicaConnection {
use TDoctrineParameterTypeMap;
/** @var string */
protected $tablePrefix;
@@ -78,7 +84,6 @@ class Connection extends PrimaryReadReplicaConnection {
private array $params,
Driver $driver,
?Configuration $config = null,
?EventManager $eventManager = null
) {
if (!isset($params['adapter'])) {
throw new \Exception('adapter not set');
@@ -89,7 +94,7 @@ class Connection extends PrimaryReadReplicaConnection {
/**
* @psalm-suppress InternalMethod
*/
parent::__construct($params, $driver, $config, $eventManager);
parent::__construct($params, $driver, $config);
$this->adapter = new $params['adapter']($this);
$this->tablePrefix = $params['tablePrefix'];
@@ -100,14 +105,11 @@ class Connection extends PrimaryReadReplicaConnection {
$this->logRequestId = $this->systemConfig->getValue('db.log_request_id', false);
$this->requestId = Server::get(IRequestId::class)->getId();
/** @var \OCP\Profiler\IProfiler */
/** @var IProfiler */
$profiler = Server::get(IProfiler::class);
if ($profiler->isEnabled()) {
$this->dbDataCollector = new DbDataCollector($this);
$this->dbDataCollector = new DbDataCollector(Server::get(IQueryLogger::class));
$profiler->add($this->dbDataCollector);
$debugStack = new BacktraceDebugStack();
$this->dbDataCollector->setDebugStack($debugStack);
$this->_config->setSQLLogger($debugStack);
}
$this->setNestTransactionsWithSavepoints(true);
@@ -116,7 +118,7 @@ class Connection extends PrimaryReadReplicaConnection {
/**
* @throws Exception
*/
public function connect($connectionName = null) {
public function connect(?string $connectionName = null): Driver\Connection {
try {
if ($this->_conn) {
$this->reconnectIfNeeded();
@@ -136,11 +138,11 @@ class Connection extends PrimaryReadReplicaConnection {
return $status;
} catch (Exception $e) {
// throw a new exception to prevent leaking info from the stacktrace
throw new Exception('Failed to connect to the database: ' . $e->getMessage(), $e->getCode());
throw new ConnectionException('Failed to connect to the database: ' . $e->getMessage(), $e->getCode());
}
}
protected function performConnect(?string $connectionName = null): bool {
protected function performConnect(?string $connectionName = null): Driver\Connection {
if (($connectionName ?? 'replica') === 'replica'
&& count($this->params['replica']) === 1
&& $this->params['primary'] === $this->params['replica'][0]) {
@@ -174,26 +176,13 @@ class Connection extends PrimaryReadReplicaConnection {
* @return \Doctrine\DBAL\Query\QueryBuilder
* @deprecated please use $this->getQueryBuilder() instead
*/
public function createQueryBuilder() {
public function createQueryBuilder(): \Doctrine\DBAL\Query\QueryBuilder {
$backtrace = $this->getCallerBacktrace();
$this->logger->debug('Doctrine QueryBuilder retrieved in {backtrace}', ['app' => 'core', 'backtrace' => $backtrace]);
$this->queriesBuilt++;
return parent::createQueryBuilder();
}
/**
* Gets the ExpressionBuilder for the connection.
*
* @return \Doctrine\DBAL\Query\Expression\ExpressionBuilder
* @deprecated please use $this->getQueryBuilder()->expr() instead
*/
public function getExpressionBuilder() {
$backtrace = $this->getCallerBacktrace();
$this->logger->debug('Doctrine ExpressionBuilder retrieved in {backtrace}', ['app' => 'core', 'backtrace' => $backtrace]);
$this->queriesBuilt++;
return parent::getExpressionBuilder();
}
/**
* Get the file and line that called the method where `getCallerBacktrace()` was used
*
@@ -301,6 +290,7 @@ class Connection extends PrimaryReadReplicaConnection {
$sql = $this->finishQuery($sql);
$this->queriesExecuted++;
$this->logQueryToFile($sql);
$types = array_map($this->convertParameterTypeToDoctrine(...), $types);
return parent::executeQuery($sql, $params, $types, $qcp);
}
@@ -318,10 +308,7 @@ class Connection extends PrimaryReadReplicaConnection {
* @throws Exception
*/
public function executeUpdate(string $sql, array $params = [], array $types = []): int {
$sql = $this->finishQuery($sql);
$this->queriesExecuted++;
$this->logQueryToFile($sql);
return parent::executeUpdate($sql, $params, $types);
return $this->executeStatement($sql, $params, $types);
}
/**
@@ -334,7 +321,7 @@ class Connection extends PrimaryReadReplicaConnection {
* @param array $params The query parameters.
* @param array $types The parameter types.
*
* @return int The number of affected rows.
* @return int The number of affected rows, if the result is bigger than PHP_INT_MAX, PHP_INT_MAX is returned
*
* @throws \Doctrine\DBAL\Exception
*/
@@ -472,22 +459,22 @@ class Connection extends PrimaryReadReplicaConnection {
foreach ($values as $name => $value) {
$updateQb->set($name, $updateQb->createNamedParameter($value, $this->getType($value)));
}
$where = $updateQb->expr()->andX();
$where = [];
$whereValues = array_merge($keys, $updatePreconditionValues);
foreach ($whereValues as $name => $value) {
if ($value === '') {
$where->add($updateQb->expr()->emptyString(
$where[] = $updateQb->expr()->emptyString(
$name
));
);
} else {
$where->add($updateQb->expr()->eq(
$where[] = $updateQb->expr()->eq(
$name,
$updateQb->createNamedParameter($value, $this->getType($value)),
$this->getType($value)
));
);
}
}
$updateQb->where($where);
$updateQb->where($updateQb->expr()->andX(...$where));
$affected = $updateQb->executeStatement();
if ($affected === 0 && !empty($updatePreconditionValues)) {
@@ -561,7 +548,7 @@ class Connection extends PrimaryReadReplicaConnection {
*/
public function dropTable($table) {
$table = $this->tablePrefix . trim($table);
$schema = $this->getSchemaManager();
$schema = $this->createSchemaManager();
if ($schema->tablesExist([$table])) {
$schema->dropTable($table);
}
@@ -577,7 +564,7 @@ class Connection extends PrimaryReadReplicaConnection {
*/
public function tableExists($table) {
$table = $this->tablePrefix . trim($table);
$schema = $this->getSchemaManager();
$schema = $this->createSchemaManager();
return $schema->tablesExist([$table]);
}
@@ -671,7 +658,7 @@ class Connection extends PrimaryReadReplicaConnection {
$platform = $this->getDatabasePlatform();
$config = \OC::$server->getConfig();
$dispatcher = Server::get(\OCP\EventDispatcher\IEventDispatcher::class);
if ($platform instanceof SqlitePlatform) {
if ($platform instanceof SQLitePlatform) {
return new SQLiteMigrator($this, $config, $dispatcher);
} elseif ($platform instanceof OraclePlatform) {
return new OracleMigrator($this, $config, $dispatcher);
@@ -680,15 +667,15 @@ class Connection extends PrimaryReadReplicaConnection {
}
}
public function beginTransaction() {
public function beginTransaction(): void {
if (!$this->inTransaction()) {
$this->transactionActiveSince = microtime(true);
}
return parent::beginTransaction();
parent::beginTransaction();
}
public function commit() {
$result = parent::commit();
public function commit(): void {
parent::commit();
if ($this->getTransactionNestingLevel() === 0) {
$timeTook = microtime(true) - $this->transactionActiveSince;
$this->transactionActiveSince = null;
@@ -696,11 +683,10 @@ class Connection extends PrimaryReadReplicaConnection {
$this->logger->debug('Transaction took ' . $timeTook . 's', ['exception' => new \Exception('Transaction took ' . $timeTook . 's')]);
}
}
return $result;
}
public function rollBack() {
$result = parent::rollBack();
public function rollBack(): void {
parent::rollBack();
if ($this->getTransactionNestingLevel() === 0) {
$timeTook = microtime(true) - $this->transactionActiveSince;
$this->transactionActiveSince = null;
@@ -708,7 +694,6 @@ class Connection extends PrimaryReadReplicaConnection {
$this->logger->debug('Transaction rollback took longer than 1s: ' . $timeTook, ['exception' => new \Exception('Long running transaction rollback')]);
}
}
return $result;
}
private function reconnectIfNeeded(): void {
@@ -721,7 +706,7 @@ class Connection extends PrimaryReadReplicaConnection {
}
try {
$this->_conn->query($this->getDriver()->getDatabasePlatform()->getDummySelectSQL());
$this->_conn->query($this->getDatabasePlatform()->getDummySelectSQL());
$this->lastConnectionCheck[$this->getConnectionName()] = time();
} catch (ConnectionLost|\Exception $e) {
$this->logger->warning('Exception during connectivity check, closing and reconnecting', ['exception' => $e]);
@@ -732,4 +717,19 @@ class Connection extends PrimaryReadReplicaConnection {
private function getConnectionName(): string {
return $this->isConnectedToPrimary() ? 'primary' : 'replica';
}
public function getDatabaseProvider(): string {
$platform = $this->getDatabasePlatform();
if ($platform instanceof MySQLPlatform) {
return IDBConnection::PLATFORM_MYSQL;
} elseif ($platform instanceof OraclePlatform) {
return IDBConnection::PLATFORM_ORACLE;
} elseif ($platform instanceof PostgreSQLPlatform) {
return IDBConnection::PLATFORM_POSTGRES;
} elseif ($platform instanceof SQLitePlatform) {
return IDBConnection::PLATFORM_SQLITE;
} else {
throw new \Exception('Database ' . $platform::class . ' not supported');
}
}
}

View File

@@ -13,7 +13,7 @@ use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Platforms\OraclePlatform;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Platforms\SQLitePlatform;
use Doctrine\DBAL\Schema\Schema;
use OC\DB\Exceptions\DbalException;
use OCP\DB\IPreparedStatement;
@@ -25,11 +25,9 @@ use OCP\IDBConnection;
* Adapts the public API to our internal DBAL connection wrapper
*/
class ConnectionAdapter implements IDBConnection {
/** @var Connection */
private $inner;
public function __construct(Connection $inner) {
$this->inner = $inner;
public function __construct(
protected Connection $inner,
) {
}
public function getQueryBuilder(): IQueryBuilder {
@@ -162,7 +160,8 @@ class ConnectionAdapter implements IDBConnection {
public function connect(): bool {
try {
return $this->inner->connect();
$this->inner->connect();
return true;
} catch (Exception $e) {
throw DbalException::wrap($e);
}
@@ -172,12 +171,21 @@ class ConnectionAdapter implements IDBConnection {
$this->inner->close();
}
/**
* @param mixed $input
* @param int $type
* @deprecated 30.0.0 Only strings are supported as database type in the end and the $type parameter is ignored going forward
*/
public function quote($input, $type = IQueryBuilder::PARAM_STR) {
return $this->inner->quote($input, $type);
if ($type !== IQueryBuilder::PARAM_STR) {
\OC::$server->getLogger()->debug('Parameter $type is no longer supported and the function only handles resulting database type string', ['exception' => new \InvalidArgumentException('$type parameter is no longer supported')]);
}
return $this->inner->getDatabasePlatform()->quoteStringLiteral($input);
}
/**
* @todo we are leaking a 3rdparty type here
* @deprecated 30.0.0 Use {@see getDatabaseProvider()} instead
*/
public function getDatabasePlatform(): AbstractPlatform {
return $this->inner->getDatabasePlatform();
@@ -230,18 +238,10 @@ class ConnectionAdapter implements IDBConnection {
return $this->inner;
}
/**
* @return self::PLATFORM_MYSQL|self::PLATFORM_ORACLE|self::PLATFORM_POSTGRES|self::PLATFORM_SQLITE
*/
public function getDatabaseProvider(): string {
$platform = $this->inner->getDatabasePlatform();
if ($platform instanceof MySQLPlatform) {
return IDBConnection::PLATFORM_MYSQL;
} elseif ($platform instanceof OraclePlatform) {
return IDBConnection::PLATFORM_ORACLE;
} elseif ($platform instanceof PostgreSQLPlatform) {
return IDBConnection::PLATFORM_POSTGRES;
} elseif ($platform instanceof SqlitePlatform) {
return IDBConnection::PLATFORM_SQLITE;
} else {
throw new \Exception('Database ' . $platform::class . ' not supported');
}
return $this->inner->getDatabaseProvider();
}
}

View File

@@ -7,11 +7,16 @@
*/
namespace OC\DB;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\Configuration;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Event\Listeners\OracleSessionInit;
use OC\DB\Logging\Middleware;
use OC\DB\Middlewares\SetTransactionIsolationLevel;
use OC\DB\Middlewares\SQLiteCaseSensitiveLike;
use OC\DB\Middlewares\SQLiteJournalMode;
use OC\SystemConfig;
use OCP\Diagnostics\IQueryLogger;
use OCP\Profiler\IProfiler;
use OCP\Server;
/**
* Takes care of creating and configuring Doctrine connections.
@@ -103,9 +108,17 @@ class ConnectionFactory {
*/
public function getConnection($type, $additionalConnectionParams) {
$normalizedType = $this->normalizeType($type);
$eventManager = new EventManager();
$eventManager->addEventSubscriber(new SetTransactionIsolationLevel());
$additionalConnectionParams = array_merge($this->createConnectionParams(), $additionalConnectionParams);
$doctrineConfiguration = new Configuration();
$doctrineMiddlewares = $doctrineConfiguration->getMiddlewares();
/** @var IProfiler */
$profiler = Server::get(IProfiler::class);
if ($profiler->isEnabled()) {
$doctrineMiddlewares[] = new Middleware(Server::get(IQueryLogger::class));
}
$doctrineMiddlewares[] = new SetTransactionIsolationLevel();
switch ($normalizedType) {
case 'pgsql':
// pg_connect used by Doctrine DBAL does not support URI notation (enclosed in brackets)
@@ -117,7 +130,8 @@ class ConnectionFactory {
break;
case 'oci':
$eventManager->addEventSubscriber(new OracleSessionInit);
$doctrineMiddlewares[] = new \Doctrine\DBAL\Driver\OCI8\Middleware\InitializeSession();
// the driverOptions are unused in dbal and need to be mapped to the parameters
if (isset($additionalConnectionParams['driverOptions'])) {
$additionalConnectionParams = array_merge($additionalConnectionParams, $additionalConnectionParams['driverOptions']);
@@ -137,16 +151,26 @@ class ConnectionFactory {
case 'sqlite3':
$journalMode = $additionalConnectionParams['sqlite.journal_mode'];
$additionalConnectionParams['platform'] = new OCSqlitePlatform();
$eventManager->addEventSubscriber(new SQLiteSessionInit(true, $journalMode));
$doctrineMiddlewares[] = new \Doctrine\DBAL\Driver\AbstractSQLiteDriver\Middleware\EnableForeignKeys();
$doctrineMiddlewares[] = new SQLiteCaseSensitiveLike();
SQLiteJournalMode::$journalMode = $additionalConnectionParams['sqlite.journal_mode'];
$doctrineMiddlewares[] = new SQLiteJournalMode();
break;
}
$doctrineConfiguration->setMiddlewares($doctrineMiddlewares);
/** @var Connection $connection */
$connection = DriverManager::getConnection(
$additionalConnectionParams,
new Configuration(),
$eventManager
$doctrineConfiguration,
);
if ($normalizedType === 'sqlite3') {
$pdo = $connection->getNativeConnection();
$pdo->sqliteCreateFunction('md5', 'md5', 1);
}
return $connection;
}

View File

@@ -8,31 +8,22 @@ declare(strict_types = 1);
namespace OC\DB;
use Doctrine\DBAL\Types\ConversionException;
use Doctrine\DBAL\Types\Type;
use OC\AppFramework\Http\Request;
use OC\Diagnostics\Query;
use OCP\AppFramework\Http\Response;
use OCP\Diagnostics\IQueryLogger;
class DbDataCollector extends \OCP\DataCollector\AbstractDataCollector {
protected ?BacktraceDebugStack $debugStack = null;
private Connection $connection;
/**
* DbDataCollector constructor.
*/
public function __construct(Connection $connection) {
$this->connection = $connection;
}
public function setDebugStack(BacktraceDebugStack $debugStack, $name = 'default'): void {
$this->debugStack = $debugStack;
public function __construct(
private readonly IQueryLogger $queryLogger,
) {
}
/**
* @inheritDoc
*/
public function collect(Request $request, Response $response, ?\Throwable $exception = null): void {
$queries = $this->sanitizeQueries($this->debugStack->queries);
$queries = $this->sanitizeQueries($this->queryLogger->getQueries());
$this->data = [
'queries' => $queries,
@@ -55,37 +46,19 @@ class DbDataCollector extends \OCP\DataCollector\AbstractDataCollector {
return $queries;
}
private function sanitizeQuery(array $query): array {
$query['explainable'] = true;
$query['runnable'] = true;
if ($query['params'] === null) {
$query['params'] = [];
}
if (!\is_array($query['params'])) {
$query['params'] = [$query['params']];
}
if (!\is_array($query['types'])) {
$query['types'] = [];
}
foreach ($query['params'] as $j => $param) {
$e = null;
if (isset($query['types'][$j])) {
// Transform the param according to the type
$type = $query['types'][$j];
if (\is_string($type)) {
$type = Type::getType($type);
}
if ($type instanceof Type) {
$query['types'][$j] = $type->getBindingType();
try {
$param = $type->convertToDatabaseValue($param, $this->connection->getDatabasePlatform());
} catch (\TypeError $e) {
} catch (ConversionException $e) {
}
}
}
private function sanitizeQuery(Query $queryObject): array {
$query = [
'sql' => $queryObject->getSql(),
'params' => $queryObject->getParams() ?? [],
'types' => $queryObject->getTypes() ?? [],
'executionMS' => $queryObject->getDuration(),
'backtrace' => $queryObject->getStacktrace(),
'explainable' => true,
'runnable' => true,
];
[$query['params'][$j], $explainable, $runnable] = $this->sanitizeParam($param, $e);
foreach ($query['params'] as $j => $param) {
[$query['params'][$j], $explainable, $runnable] = $this->sanitizeParam($param);
if (!$explainable) {
$query['explainable'] = false;
}
@@ -105,20 +78,16 @@ class DbDataCollector extends \OCP\DataCollector\AbstractDataCollector {
* indicating if the original value was kept (allowing to use the sanitized
* value to explain the query).
*/
private function sanitizeParam($var, ?\Throwable $error): array {
private function sanitizeParam($var): array {
if (\is_object($var)) {
return [$o = new ObjectParameter($var, $error), false, $o->isStringable() && !$error];
}
if ($error) {
return ['⚠ '.$error->getMessage(), false, false];
return [$o = new ObjectParameter($var, null), false, $o->isStringable()];
}
if (\is_array($var)) {
$a = [];
$explainable = $runnable = true;
foreach ($var as $k => $v) {
[$value, $e, $r] = $this->sanitizeParam($v, null);
[$value, $e, $r] = $this->sanitizeParam($v);
$explainable = $explainable && $e;
$runnable = $runnable && $r;
$a[$k] = $value;

View File

@@ -24,6 +24,7 @@ use Doctrine\DBAL\Exception\RetryableException;
use Doctrine\DBAL\Exception\ServerException;
use Doctrine\DBAL\Exception\SyntaxErrorException;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Doctrine\DBAL\Types\Exception\TypeNotRegistered;
use OCP\DB\Exception;
/**
@@ -83,6 +84,9 @@ class DbalException extends Exception {
/**
* Other server errors
*/
if ($this->original instanceof TypeNotRegistered) {
return parent::REASON_TYPE_UNKNOWN;
}
if ($this->original instanceof LockWaitTimeoutException) {
return parent::REASON_LOCK_WAIT_TIMEOUT;
}

View File

@@ -0,0 +1,49 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2024 Doctrine Project
* SPDX-License-Identifier: MIT
*/
namespace OC\DB\Logging;
use Doctrine\DBAL\Driver\Connection as ConnectionInterface;
use Doctrine\DBAL\Driver\Middleware\AbstractConnectionMiddleware;
use Doctrine\DBAL\Driver\Result;
use Doctrine\DBAL\Driver\Statement as DriverStatement;
use OCP\Diagnostics\IQueryLogger;
final class Connection extends AbstractConnectionMiddleware {
public function __construct(
ConnectionInterface $connection,
private readonly IQueryLogger $queryLogger,
) {
parent::__construct($connection);
}
public function prepare(string $sql): DriverStatement {
return new Statement(
parent::prepare($sql),
$this->queryLogger,
$sql,
);
}
public function query(string $sql): Result {
$this->queryLogger->startQuery($sql);
$result = parent::query($sql);
$this->queryLogger->stopQuery();
return $result;
}
public function exec(string $sql): int|string {
$this->queryLogger->startQuery($sql);
$result = parent::exec($sql);
$this->queryLogger->stopQuery();
return $result;
}
}

View File

@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2024 Doctrine Project
* SPDX-License-Identifier: MIT
*/
namespace OC\DB\Logging;
use Doctrine\DBAL\Driver as DriverInterface;
use Doctrine\DBAL\Driver\Middleware\AbstractDriverMiddleware;
use OCP\Diagnostics\IQueryLogger;
use SensitiveParameter;
final class Driver extends AbstractDriverMiddleware {
public function __construct(
DriverInterface $driver,
private readonly IQueryLogger $queryLogger,
) {
parent::__construct($driver);
}
public function connect(
#[SensitiveParameter]
array $params,
): Connection {
return new Connection(
parent::connect($params),
$this->queryLogger,
);
}
}

View File

@@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2024 Doctrine Project
* SPDX-License-Identifier: MIT
*/
namespace OC\DB\Logging;
use Doctrine\DBAL\Driver as DriverInterface;
use Doctrine\DBAL\Driver\Middleware as MiddlewareInterface;
use OCP\Diagnostics\IQueryLogger;
final class Middleware implements MiddlewareInterface {
public function __construct(
private readonly IQueryLogger $queryLogger,
) {
}
public function wrap(DriverInterface $driver): DriverInterface {
return new Driver(
$driver,
$this->queryLogger,
);
}
}

View File

@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2024 Doctrine Project
* SPDX-License-Identifier: MIT
*/
namespace OC\DB\Logging;
use Doctrine\DBAL\Driver\Middleware\AbstractStatementMiddleware;
use Doctrine\DBAL\Driver\Result as ResultInterface;
use Doctrine\DBAL\Driver\Statement as StatementInterface;
use Doctrine\DBAL\ParameterType;
use OC\DB\TDoctrineParameterTypeMap;
use OCP\Diagnostics\IQueryLogger;
final class Statement extends AbstractStatementMiddleware {
use TDoctrineParameterTypeMap;
/** @var array<int,mixed>|array<string,mixed> */
private array $params = [];
/** @var array<int,string>|array<string,string> */
private array $types = [];
public function __construct(
StatementInterface $statement,
private readonly IQueryLogger $queryLogger,
private readonly string $sql,
) {
parent::__construct($statement);
}
public function bindValue(int|string $param, mixed $value, ParameterType $type): void {
$this->params[$param] = $value;
$this->types[$param] = $this->convertParameterTypeToJsonSerializable($type);
parent::bindValue($param, $value, $type);
}
public function execute(): ResultInterface {
$this->queryLogger->startQuery($this->sql, $this->params, $this->types);
$result = parent::execute();
$this->queryLogger->stopQuery();
return $result;
}
}

View File

@@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\DB\Middlewares;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\Connection;
use Doctrine\DBAL\Driver\Middleware;
use Doctrine\DBAL\Driver\Middleware\AbstractDriverMiddleware;
final class SQLiteCaseSensitiveLike implements Middleware {
public function wrap(Driver $driver): Driver {
return new class($driver) extends AbstractDriverMiddleware {
/**
* {@inheritDoc}
*/
public function connect(
#[\SensitiveParameter]
array $params,
): Connection {
$connection = parent::connect($params);
$connection->exec('PRAGMA case_sensitive_like = true');
return $connection;
}
};
}
}

View File

@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\DB\Middlewares;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\Connection;
use Doctrine\DBAL\Driver\Middleware;
use Doctrine\DBAL\Driver\Middleware\AbstractDriverMiddleware;
class SQLiteJournalMode implements Middleware {
public static string $journalMode = 'WAL';
public function wrap(Driver $driver): Driver {
return new class($driver) extends AbstractDriverMiddleware {
/**
* {@inheritDoc}
*/
public function connect(
#[\SensitiveParameter]
array $params,
): Connection {
$connection = parent::connect($params);
$connection->exec('PRAGMA journal_mode = ' . SQLiteJournalMode::$journalMode);
return $connection;
}
};
}
}

View File

@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\DB\Middlewares;
use Doctrine\DBAL\Connections\PrimaryReadReplicaConnection;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\Connection;
use Doctrine\DBAL\Driver\Middleware;
use Doctrine\DBAL\Driver\Middleware\AbstractDriverMiddleware;
use Doctrine\DBAL\Platforms\MySQLPlatform;
final class SetTransactionIsolationLevel implements Middleware {
public function wrap(Driver $driver): Driver {
return new class($driver) extends AbstractDriverMiddleware {
/**
* {@inheritDoc}
*/
public function connect(
#[\SensitiveParameter]
array $params,
): Connection {
$connection = parent::connect($params);
if ($connection instanceof PrimaryReadReplicaConnection && $connection->isConnectedToPrimary()) {
$connection->setTransactionIsolation(\Doctrine\DBAL\TransactionIsolationLevel::READ_COMMITTED);
if ($connection->getDatabasePlatform() instanceof MySQLPlatform) {
$connection->executeStatement('SET SESSION AUTOCOMMIT=1');
}
}
return $connection;
}
};
}
}

View File

@@ -6,20 +6,19 @@
*/
namespace OC\DB;
use Doctrine\DBAL\Platforms\OraclePlatform;
use Doctrine\DBAL\Platforms\PostgreSQL94Platform;
use Doctrine\DBAL\Schema\Index;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\SchemaException;
use Doctrine\DBAL\Schema\Sequence;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Types\Types;
use OC\App\InfoParser;
use OC\IntegrityCheck\Helpers\AppLocator;
use OC\Migration\SimpleOutput;
use OCP\AppFramework\App;
use OCP\AppFramework\QueryException;
use OCP\DB\ISchemaWrapper;
use OCP\DB\Types;
use OCP\IDBConnection;
use OCP\Migration\IMigrationStep;
use OCP\Migration\IOutput;
use OCP\Server;
@@ -419,6 +418,7 @@ class MigrationService {
if ($toSchema instanceof SchemaWrapper) {
$this->output->debug('- Checking target database schema');
$targetSchema = $toSchema->getWrappedSchema();
$this->ensureVarcharLength($targetSchema);
$this->ensureUniqueNamesConstraints($targetSchema, true);
if ($this->checkOracle) {
$beforeSchema = $this->connection->createSchema();
@@ -500,6 +500,7 @@ class MigrationService {
if ($toSchema instanceof SchemaWrapper) {
$targetSchema = $toSchema->getWrappedSchema();
$this->ensureVarcharLength($targetSchema);
$this->ensureUniqueNamesConstraints($targetSchema, $schemaOnly);
if ($this->checkOracle) {
$sourceSchema = $this->connection->createSchema();
@@ -565,7 +566,7 @@ class MigrationService {
throw new \InvalidArgumentException('Column "' . $table->getName() . '"."' . $thing->getName() . '" is NotNull, but has empty string or null as default.');
}
if ($thing->getNotnull() && $thing->getType()->getName() === Types::BOOLEAN) {
if ($thing->getNotnull() && Types::getType($thing->getType()) === Types::BOOLEAN) {
throw new \InvalidArgumentException('Column "' . $table->getName() . '"."' . $thing->getName() . '" is type Bool and also NotNull, so it can not store "false".');
}
@@ -576,8 +577,8 @@ class MigrationService {
// If the column was just created OR the length changed OR the type changed
// we will NOT detect invalid length if the column is not modified
if (($sourceColumn === null || $sourceColumn->getLength() !== $thing->getLength() || $sourceColumn->getType()->getName() !== Types::STRING)
&& $thing->getLength() > 4000 && $thing->getType()->getName() === Types::STRING) {
if (($sourceColumn === null || $sourceColumn->getLength() !== $thing->getLength() || Types::getType($sourceColumn->getType()) !== Types::STRING)
&& $thing->getLength() > 4000 && Types::getType($thing->getType()) === Types::STRING) {
throw new \InvalidArgumentException('Column "' . $table->getName() . '"."' . $thing->getName() . '" is type String, but exceeding the 4.000 length limit.');
}
}
@@ -595,11 +596,11 @@ class MigrationService {
}
$primaryKey = $table->getPrimaryKey();
if ($primaryKey instanceof Index && (!$sourceTable instanceof Table || !$sourceTable->hasPrimaryKey())) {
if ($primaryKey instanceof Index && (!$sourceTable instanceof Table || !$sourceTable->getPrimaryKey())) {
$indexName = strtolower($primaryKey->getName());
$isUsingDefaultName = $indexName === 'primary';
if ($this->connection->getDatabasePlatform() instanceof PostgreSQL94Platform) {
if ($this->connection->getDatabaseProvider() === IDBConnection::PLATFORM_POSTGRES) {
$defaultName = $table->getName() . '_pkey';
$isUsingDefaultName = strtolower($defaultName) === $indexName;
@@ -609,7 +610,7 @@ class MigrationService {
return $sequence->getName() !== $sequenceName;
});
}
} elseif ($this->connection->getDatabasePlatform() instanceof OraclePlatform) {
} elseif ($this->connection->getDatabaseProvider() === IDBConnection::PLATFORM_ORACLE) {
$defaultName = $table->getName() . '_seq';
$isUsingDefaultName = strtolower($defaultName) === $indexName;
}
@@ -712,6 +713,23 @@ class MigrationService {
}
}
/**
* Ensure VARCHAR columns have a default length (required since Doctrine/DBAL 4.0)
*
* @param Schema $targetSchema
*/
public function ensureVarcharLength(Schema $targetSchema): void {
foreach ($targetSchema->getTables() as $table) {
foreach ($table->getColumns() as $column) {
if ($column->getLength() === null) {
if ($column->getType()->getTypeRegistry()->lookupName($column->getType()) === 'string') {
$column->setLength(255);
}
}
}
}
}
protected function logErrorOrWarning(string $log): void {
if ($this->output instanceof SimpleOutput) {
$this->output->warning($log);

View File

@@ -1,11 +0,0 @@
<?php
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB;
class OCSqlitePlatform extends \Doctrine\DBAL\Platforms\SqlitePlatform {
}

View File

@@ -8,20 +8,18 @@
namespace OC\DB;
class OracleConnection extends Connection {
/** @var array<string, int> */
protected array $lastInsertId = [];
/**
* Quote the keys of the array
* @param array<string, string> $data
* @return array<string, string>
*/
private function quoteKeys(array $data) {
private function quoteKeys(array $data): array {
$return = [];
$c = $this->getDatabasePlatform()->getIdentifierQuoteCharacter();
foreach ($data as $key => $value) {
if ($key[0] !== $c) {
$return[$this->quoteIdentifier($key)] = $value;
} else {
$return[$key] = $value;
}
$return[$this->quoteIdentifier($key)] = $value;
}
return $return;
}
@@ -29,10 +27,8 @@ class OracleConnection extends Connection {
/**
* {@inheritDoc}
*/
public function insert($table, array $data, array $types = []) {
if ($table[0] !== $this->getDatabasePlatform()->getIdentifierQuoteCharacter()) {
$table = $this->quoteIdentifier($table);
}
public function insert(string $table, array $data, array $types = []): int|string {
$table = $this->quoteIdentifier($table);
$data = $this->quoteKeys($data);
return parent::insert($table, $data, $types);
}
@@ -40,10 +36,8 @@ class OracleConnection extends Connection {
/**
* {@inheritDoc}
*/
public function update($table, array $data, array $criteria, array $types = []) {
if ($table[0] !== $this->getDatabasePlatform()->getIdentifierQuoteCharacter()) {
$table = $this->quoteIdentifier($table);
}
public function update(string $table, array $data, array $criteria = [], array $types = []): int|string {
$table = $this->quoteIdentifier($table);
$data = $this->quoteKeys($data);
$criteria = $this->quoteKeys($criteria);
return parent::update($table, $data, $criteria, $types);
@@ -52,10 +46,8 @@ class OracleConnection extends Connection {
/**
* {@inheritDoc}
*/
public function delete($table, array $criteria, array $types = []) {
if ($table[0] !== $this->getDatabasePlatform()->getIdentifierQuoteCharacter()) {
$table = $this->quoteIdentifier($table);
}
public function delete(string $table, array $criteria = [], array $types = []): int|string {
$table = $this->quoteIdentifier($table);
$criteria = $this->quoteKeys($criteria);
return parent::delete($table, $criteria);
}
@@ -65,10 +57,10 @@ class OracleConnection extends Connection {
*
* @param string $table table name without the prefix
*/
public function dropTable($table) {
public function dropTable($table): void {
$table = $this->tablePrefix . trim($table);
$table = $this->quoteIdentifier($table);
$schema = $this->getSchemaManager();
$schema = $this->createSchemaManager();
if ($schema->tablesExist([$table])) {
$schema->dropTable($table);
}
@@ -80,10 +72,45 @@ class OracleConnection extends Connection {
* @param string $table table name without the prefix
* @return bool
*/
public function tableExists($table) {
public function tableExists($table): bool {
$table = $this->tablePrefix . trim($table);
$table = $this->quoteIdentifier($table);
$schema = $this->getSchemaManager();
$schema = $this->createSchemaManager();
return $schema->tablesExist([$table]);
}
/**
* Executes an SQL INSERT/UPDATE/DELETE query with the given parameters
* and returns the number of affected rows.
*
* This method supports PDO binding types as well as DBAL mapping types.
*
* @param string $sql The SQL query.
* @param array $params The query parameters.
* @param array $types The parameter types.
*
* @return int The number of affected rows, if the result is bigger than PHP_INT_MAX, PHP_INT_MAX is returned
*
* @throws \Doctrine\DBAL\Exception
*/
public function executeStatement($sql, array $params = [], array $types = []): int {
$returned = parent::executeStatement($sql, $params, $types);
var_dump($sql);
if (preg_match('/^DECLARE vRowid ROWID; BEGIN INSERT INTO (.*) VALUES (.*) INTO (.*)$/', $sql, $matches)) {
var_dump($returned);
$this->lastInsertId[$matches[1]] = $returned;
var_dump($this->lastInsertId);
$returned = 1;
}
return $returned;
}
public function lastInsertId($name = null): int {
if ($name) {
$name = $this->replaceTablePrefix($name);
}
return $this->lastInsertId[$name];
}
}

View File

@@ -43,7 +43,7 @@ class PgSqlTools {
return preg_match($filterExpression, $asset) !== false;
});
foreach ($conn->getSchemaManager()->listSequences() as $sequence) {
foreach ($conn->createSchemaManager()->listSequences() as $sequence) {
$sequenceName = $sequence->getName();
$sqlInfo = 'SELECT table_schema, table_name, column_name
FROM information_schema.columns

View File

@@ -8,11 +8,10 @@ declare(strict_types=1);
*/
namespace OC\DB;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Statement;
use OCP\DB\IPreparedStatement;
use OCP\DB\IResult;
use OCP\DB\QueryBuilder\IQueryBuilder;
use PDO;
/**
@@ -25,6 +24,8 @@ use PDO;
* methods without much magic.
*/
class PreparedStatement implements IPreparedStatement {
use TDoctrineParameterTypeMap;
/** @var Statement */
private $statement;
@@ -57,16 +58,31 @@ class PreparedStatement implements IPreparedStatement {
return $this->getResult()->fetchOne();
}
public function bindValue($param, $value, $type = ParameterType::STRING): bool {
return $this->statement->bindValue($param, $value, $type);
public function bindValue($param, $value, $type = IQueryBuilder::PARAM_STR): bool {
$this->statement->bindValue($param, $value, $this->convertParameterTypeToDoctrine($type));
return true;
}
public function bindParam($param, &$variable, $type = ParameterType::STRING, $length = null): bool {
return $this->statement->bindParam($param, $variable, $type, $length);
public function bindParam($param, &$variable, $type = IQueryBuilder::PARAM_STR, $length = null): bool {
if ($type !== IQueryBuilder::PARAM_STR) {
\OC::$server->getLogger()->warning('PreparedStatement::bindParam() is no longer supported. Use bindValue() instead.', ['exception' => new \BadMethodCallException('bindParam() is no longer supported')]);
}
$this->bindValue($param, $variable, $type);
return true;
}
public function execute($params = null): IResult {
return ($this->result = new ResultAdapter($this->statement->execute($params)));
if ($params !== null) {
foreach ($params as $key => $param) {
if (is_int($key)) {
// Parameter count starts with 1
$this->bindValue($key + 1, $param);
} else {
$this->bindValue($key, $param);
}
}
}
return ($this->result = new ResultAdapter($this->statement->executeQuery()));
}
public function rowCount(): int {
@@ -78,6 +94,6 @@ class PreparedStatement implements IPreparedStatement {
return $this->result;
}
throw new Exception("You have to execute the prepared statement before accessing the results");
throw new \Exception("You have to execute the prepared statement before accessing the results");
}
}

View File

@@ -30,7 +30,9 @@ class CompositeExpression implements ICompositeExpression, \Countable {
* @return \OCP\DB\QueryBuilder\ICompositeExpression
*/
public function addMultiple(array $parts = []): ICompositeExpression {
$this->compositeExpression->addMultiple($parts);
foreach ($parts as $part) {
$this->add($part);
}
return $this;
}
@@ -43,8 +45,7 @@ class CompositeExpression implements ICompositeExpression, \Countable {
* @return \OCP\DB\QueryBuilder\ICompositeExpression
*/
public function add($part): ICompositeExpression {
$this->compositeExpression->add($part);
$this->compositeExpression = $this->compositeExpression->with($part);
return $this;
}

View File

@@ -63,7 +63,7 @@ class ExpressionBuilder implements IExpressionBuilder {
* @return \OCP\DB\QueryBuilder\ICompositeExpression
*/
public function andX(...$x): ICompositeExpression {
$compositeExpression = call_user_func_array([$this->expressionBuilder, 'andX'], $x);
$compositeExpression = call_user_func_array([$this->expressionBuilder, 'and'], $x);
return new CompositeExpression($compositeExpression);
}
@@ -82,7 +82,7 @@ class ExpressionBuilder implements IExpressionBuilder {
* @return \OCP\DB\QueryBuilder\ICompositeExpression
*/
public function orX(...$x): ICompositeExpression {
$compositeExpression = call_user_func_array([$this->expressionBuilder, 'orX'], $x);
$compositeExpression = call_user_func_array([$this->expressionBuilder, 'or'], $x);
return new CompositeExpression($compositeExpression);
}
@@ -288,7 +288,7 @@ class ExpressionBuilder implements IExpressionBuilder {
* @since 9.0.0
*/
public function iLike($x, $y, $type = null): string {
return $this->expressionBuilder->like($this->functionBuilder->lower($x), $this->functionBuilder->lower($y));
return $this->expressionBuilder->like((string) $this->functionBuilder->lower($x), (string) $this->functionBuilder->lower($y));
}
/**
@@ -372,7 +372,7 @@ class ExpressionBuilder implements IExpressionBuilder {
public function bitwiseAnd($x, int $y): IQueryFunction {
return new QueryFunction($this->connection->getDatabasePlatform()->getBitAndComparisonExpression(
$this->helper->quoteColumnName($x),
$y
(string) $y
));
}
@@ -387,7 +387,7 @@ class ExpressionBuilder implements IExpressionBuilder {
public function bitwiseOr($x, int $y): IQueryFunction {
return new QueryFunction($this->connection->getDatabasePlatform()->getBitOrComparisonExpression(
$this->helper->quoteColumnName($x),
$y
(string) $y
));
}
@@ -400,7 +400,10 @@ class ExpressionBuilder implements IExpressionBuilder {
* @return ILiteral
*/
public function literal($input, $type = IQueryBuilder::PARAM_STR): ILiteral {
return new Literal($this->expressionBuilder->literal($input, $type));
if ($type !== IQueryBuilder::PARAM_STR) {
\OC::$server->getLogger()->debug('Parameter $type is no longer supported and the function only handles resulting database type string', ['exception' => new \InvalidArgumentException('$type parameter is no longer supported')]);
}
return new Literal($this->connection->getDatabasePlatform()->quoteStringLiteral((string) $input));
}
/**

View File

@@ -7,10 +7,6 @@
*/
namespace OC\DB\QueryBuilder;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Platforms\OraclePlatform;
use Doctrine\DBAL\Platforms\PostgreSQL94Platform;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Query\QueryException;
use OC\DB\ConnectionAdapter;
use OC\DB\QueryBuilder\ExpressionBuilder\ExpressionBuilder;
@@ -23,6 +19,7 @@ use OC\DB\QueryBuilder\FunctionBuilder\OCIFunctionBuilder;
use OC\DB\QueryBuilder\FunctionBuilder\PgSqlFunctionBuilder;
use OC\DB\QueryBuilder\FunctionBuilder\SqliteFunctionBuilder;
use OC\DB\ResultAdapter;
use OC\DB\TDoctrineParameterTypeMap;
use OC\SystemConfig;
use OCP\DB\IResult;
use OCP\DB\QueryBuilder\ICompositeExpression;
@@ -30,9 +27,24 @@ use OCP\DB\QueryBuilder\ILiteral;
use OCP\DB\QueryBuilder\IParameter;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\DB\QueryBuilder\IQueryFunction;
use OCP\IDBConnection;
use Psr\Log\LoggerInterface;
class QueryBuilder implements IQueryBuilder {
use TDoctrineParameterTypeMap;
/** @internal */
protected const SELECT = 0;
/** @internal */
protected const DELETE = 1;
/** @internal */
protected const UPDATE = 2;
/** @internal */
protected const INSERT = 3;
/** @var ConnectionAdapter */
private $connection;
@@ -49,6 +61,8 @@ class QueryBuilder implements IQueryBuilder {
/** @var bool */
private $automaticTablePrefix = true;
private bool $nonEmptyWhere = false;
private int $type = self::SELECT;
/** @var string */
protected $lastInsertedTable;
@@ -95,20 +109,12 @@ class QueryBuilder implements IQueryBuilder {
* @return \OCP\DB\QueryBuilder\IExpressionBuilder
*/
public function expr() {
if ($this->connection->getDatabasePlatform() instanceof OraclePlatform) {
return new OCIExpressionBuilder($this->connection, $this);
}
if ($this->connection->getDatabasePlatform() instanceof PostgreSQL94Platform) {
return new PgSqlExpressionBuilder($this->connection, $this);
}
if ($this->connection->getDatabasePlatform() instanceof MySQLPlatform) {
return new MySqlExpressionBuilder($this->connection, $this);
}
if ($this->connection->getDatabasePlatform() instanceof SqlitePlatform) {
return new SqliteExpressionBuilder($this->connection, $this);
}
return new ExpressionBuilder($this->connection, $this);
return match($this->connection->getDatabaseProvider()) {
IDBConnection::PLATFORM_ORACLE => new OCIExpressionBuilder($this->connection, $this),
IDBConnection::PLATFORM_POSTGRES => new PgSqlExpressionBuilder($this->connection, $this),
IDBConnection::PLATFORM_MYSQL => new MySqlExpressionBuilder($this->connection, $this),
IDBConnection::PLATFORM_SQLITE => new SqliteExpressionBuilder($this->connection, $this),
};
}
/**
@@ -128,13 +134,13 @@ class QueryBuilder implements IQueryBuilder {
* @return \OCP\DB\QueryBuilder\IFunctionBuilder
*/
public function func() {
if ($this->connection->getDatabasePlatform() instanceof OraclePlatform) {
if ($this->connection->getDatabaseProvider() === IDBConnection::PLATFORM_ORACLE) {
return new OCIFunctionBuilder($this->connection, $this, $this->helper);
}
if ($this->connection->getDatabasePlatform() instanceof SqlitePlatform) {
if ($this->connection->getDatabaseProvider() === IDBConnection::PLATFORM_SQLITE) {
return new SqliteFunctionBuilder($this->connection, $this, $this->helper);
}
if ($this->connection->getDatabasePlatform() instanceof PostgreSQL94Platform) {
if ($this->connection->getDatabaseProvider() === IDBConnection::PLATFORM_POSTGRES) {
return new PgSqlFunctionBuilder($this->connection, $this, $this->helper);
}
@@ -147,7 +153,7 @@ class QueryBuilder implements IQueryBuilder {
* @return integer
*/
public function getType() {
return $this->queryBuilder->getType();
return $this->type;
}
/**
@@ -162,16 +168,18 @@ class QueryBuilder implements IQueryBuilder {
/**
* Gets the state of this query builder instance.
*
* @return integer Either QueryBuilder::STATE_DIRTY or QueryBuilder::STATE_CLEAN.
* @return int Always returns 0 which is former `QueryBuilder::STATE_DIRTY`
* @deprecated 30.0.0 Function is no-op because it's removed upstream
*/
public function getState() {
return $this->queryBuilder->getState();
$this->logger->debug('Relying on the query builder state is deprecated as it is an internal concern.', ['exception' => new \Exception('Table alias provided for UPDATE query')]);
return 0;
}
/**
* Executes this query using the bound parameters and their types.
*
* Uses {@see Connection::executeQuery} for select statements and {@see Connection::executeUpdate}
* Uses {@see Connection::executeQuery} for select statements and {@see Connection::executeStatement}
* for insert, update and delete statements.
*
* @return IResult|int
@@ -207,24 +215,24 @@ class QueryBuilder implements IQueryBuilder {
}
}
if (!empty($this->getQueryPart('select'))) {
$select = $this->getQueryPart('select');
$hasSelectAll = array_filter($select, static function ($s) {
return $s === '*';
});
$hasSelectSpecific = array_filter($select, static function ($s) {
return $s !== '*';
});
//if (!empty($this->getQueryPart('select'))) {
// $select = $this->getQueryPart('select');
// $hasSelectAll = array_filter($select, static function ($s) {
// return $s === '*';
// });
// $hasSelectSpecific = array_filter($select, static function ($s) {
// return $s !== '*';
// });
if (empty($hasSelectAll) === empty($hasSelectSpecific)) {
$exception = new QueryException('Query is selecting * and specific values in the same query. This is not supported in Oracle.');
$this->logger->error($exception->getMessage(), [
'query' => $this->getSQL(),
'app' => 'core',
'exception' => $exception,
]);
}
}
// if (empty($hasSelectAll) === empty($hasSelectSpecific)) {
// $exception = new QueryException('Query is selecting * and specific values in the same query. This is not supported in Oracle.');
// $this->logger->error($exception->getMessage(), [
// 'query' => $this->getSQL(),
// 'app' => 'core',
// 'exception' => $exception,
// ]);
// }
//}
$numberOfParameters = 0;
$hasTooLargeArrayParameter = false;
@@ -254,21 +262,24 @@ class QueryBuilder implements IQueryBuilder {
]);
}
$result = $this->queryBuilder->execute();
if (is_int($result)) {
return $result;
if ($this->getType() !== self::SELECT) {
$result = $this->queryBuilder->executeStatement();
return (int) $result;
}
$result = $this->queryBuilder->executeQuery();
return new ResultAdapter($result);
}
public function executeQuery(): IResult {
if ($this->getType() !== \Doctrine\DBAL\Query\QueryBuilder::SELECT) {
if ($this->getType() !== self::SELECT) {
throw new \RuntimeException('Invalid query type, expected SELECT query');
}
try {
$result = $this->execute();
} catch (\Doctrine\DBAL\Exception $e) {
var_dump($this->getSQL(), $this->getParameters(), $this->getParameterTypes());
throw \OC\DB\Exceptions\DbalException::wrap($e);
}
@@ -280,7 +291,7 @@ class QueryBuilder implements IQueryBuilder {
}
public function executeStatement(): int {
if ($this->getType() === \Doctrine\DBAL\Query\QueryBuilder::SELECT) {
if ($this->getType() === self::SELECT) {
throw new \RuntimeException('Invalid query type, expected INSERT, DELETE or UPDATE statement');
}
@@ -332,7 +343,7 @@ class QueryBuilder implements IQueryBuilder {
* @return $this This QueryBuilder instance.
*/
public function setParameter($key, $value, $type = null) {
$this->queryBuilder->setParameter($key, $value, $type);
$this->queryBuilder->setParameter($key, $value, $this->convertParameterTypeToDoctrine($type));
return $this;
}
@@ -357,6 +368,7 @@ class QueryBuilder implements IQueryBuilder {
* @return $this This QueryBuilder instance.
*/
public function setParameters(array $params, array $types = []) {
$types = array_map($this->convertParameterTypeToDoctrine(...), $types);
$this->queryBuilder->setParameters($params, $types);
return $this;
@@ -472,12 +484,13 @@ class QueryBuilder implements IQueryBuilder {
* '@return $this This QueryBuilder instance.
*/
public function select(...$selects) {
$this->type = self::SELECT;
if (count($selects) === 1 && is_array($selects[0])) {
$selects = $selects[0];
}
$this->queryBuilder->select(
$this->helper->quoteColumnNames($selects)
...$this->helper->quoteColumnNames($selects)
);
return $this;
@@ -499,6 +512,7 @@ class QueryBuilder implements IQueryBuilder {
* @return $this This QueryBuilder instance.
*/
public function selectAlias($select, $alias) {
$this->type = self::SELECT;
$this->queryBuilder->addSelect(
$this->helper->quoteColumnName($select) . ' AS ' . $this->helper->quoteColumnName($alias)
);
@@ -520,6 +534,7 @@ class QueryBuilder implements IQueryBuilder {
* @return $this This QueryBuilder instance.
*/
public function selectDistinct($select) {
$this->type = self::SELECT;
if (!is_array($select)) {
$select = [$select];
}
@@ -549,12 +564,13 @@ class QueryBuilder implements IQueryBuilder {
* @return $this This QueryBuilder instance.
*/
public function addSelect(...$selects) {
$this->type = self::SELECT;
if (count($selects) === 1 && is_array($selects[0])) {
$selects = $selects[0];
}
$this->queryBuilder->addSelect(
$this->helper->quoteColumnNames($selects)
...$this->helper->quoteColumnNames($selects)
);
return $this;
@@ -575,11 +591,16 @@ class QueryBuilder implements IQueryBuilder {
* @param string $alias The table alias used in the constructed query.
*
* @return $this This QueryBuilder instance.
* @since 30.0.0 Alias is no longer supported
*/
public function delete($delete = null, $alias = null) {
if ($alias !== null) {
$this->logger->debug('DELETE queries with alias are no longer supported and the provided alias is ignored', ['exception' => new \InvalidArgumentException('Table alias provided for DELETE query')]);
}
$this->type = self::DELETE;
$this->queryBuilder->delete(
$this->getTableName($delete),
$alias
);
return $this;
@@ -600,11 +621,16 @@ class QueryBuilder implements IQueryBuilder {
* @param string $alias The table alias used in the constructed query.
*
* @return $this This QueryBuilder instance.
* @since 30.0.0 Alias is no longer supported
*/
public function update($update = null, $alias = null) {
if ($alias !== null) {
$this->logger->debug('UPDATE queries with alias are no longer supported and the provided alias is ignored', ['exception' => new \InvalidArgumentException('Table alias provided for UPDATE query')]);
}
$this->type = self::UPDATE;
$this->queryBuilder->update(
$this->getTableName($update),
$alias
);
return $this;
@@ -630,6 +656,7 @@ class QueryBuilder implements IQueryBuilder {
* @return $this This QueryBuilder instance.
*/
public function insert($insert = null) {
$this->type = self::INSERT;
$this->queryBuilder->insert(
$this->getTableName($insert)
);
@@ -812,9 +839,10 @@ class QueryBuilder implements IQueryBuilder {
* // You can optionally programmatically build and/or expressions
* $qb = $conn->getQueryBuilder();
*
* $or = $qb->expr()->orx();
* $or->add($qb->expr()->eq('u.id', 1));
* $or->add($qb->expr()->eq('u.id', 2));
* $or = $qb->expr()->orx(
* $qb->expr()->eq('u.id', 1),
* $qb->expr()->eq('u.id', 2),
* );
*
* $qb->update('users', 'u')
* ->set('u.password', md5('password'))
@@ -826,12 +854,14 @@ class QueryBuilder implements IQueryBuilder {
* @return $this This QueryBuilder instance.
*/
public function where(...$predicates) {
if ($this->getQueryPart('where') !== null && $this->systemConfig->getValue('debug', false)) {
if ($this->nonEmptyWhere && $this->systemConfig->getValue('debug', false)) {
// Only logging a warning, not throwing for now.
$e = new QueryException('Using where() on non-empty WHERE part, please verify it is intentional to not call andWhere() or orWhere() instead. Otherwise consider creating a new query builder object or call resetQueryPart(\'where\') first.');
$this->logger->warning($e->getMessage(), ['exception' => $e]);
}
$this->nonEmptyWhere = true;
call_user_func_array(
[$this->queryBuilder, 'where'],
$predicates
@@ -859,6 +889,7 @@ class QueryBuilder implements IQueryBuilder {
* @see where()
*/
public function andWhere(...$where) {
$this->nonEmptyWhere = true;
call_user_func_array(
[$this->queryBuilder, 'andWhere'],
$where
@@ -886,6 +917,7 @@ class QueryBuilder implements IQueryBuilder {
* @see where()
*/
public function orWhere(...$where) {
$this->nonEmptyWhere = true;
call_user_func_array(
[$this->queryBuilder, 'orWhere'],
$where
@@ -1067,7 +1099,7 @@ class QueryBuilder implements IQueryBuilder {
public function orderBy($sort, $order = null) {
$this->queryBuilder->orderBy(
$this->helper->quoteColumnName($sort),
$order
$order ?? 'ASC'
);
return $this;
@@ -1084,7 +1116,7 @@ class QueryBuilder implements IQueryBuilder {
public function addOrderBy($sort, $order = null) {
$this->queryBuilder->addOrderBy(
$this->helper->quoteColumnName($sort),
$order
$order ?? 'ASC'
);
return $this;
@@ -1096,18 +1128,20 @@ class QueryBuilder implements IQueryBuilder {
* @param string $queryPartName
*
* @return mixed
* @deprecated 30.0.0 The function always throws an exception
*/
public function getQueryPart($queryPartName) {
return $this->queryBuilder->getQueryPart($queryPartName);
throw new \Exception('Getting query parts is no longer supported as they are implementation details.');
}
/**
* Gets all query parts.
*
* @return array
* @deprecated 30.0.0 The function always throws an exception
*/
public function getQueryParts() {
return $this->queryBuilder->getQueryParts();
throw new \Exception('Getting query parts is no longer supported as they are implementation details.');
}
/**
@@ -1116,9 +1150,20 @@ class QueryBuilder implements IQueryBuilder {
* @param array|null $queryPartNames
*
* @return $this This QueryBuilder instance.
* @since 30.0.0 Only null and a list of 'where'|'having'|'groupBy'|'orderBy' is supported. Everything else will throw.
*/
public function resetQueryParts($queryPartNames = null) {
$this->queryBuilder->resetQueryParts($queryPartNames);
if ($queryPartNames === null) {
$this->queryBuilder->resetWhere();
$this->queryBuilder->resetHaving();
$this->queryBuilder->resetGroupBy();
$this->queryBuilder->resetOrderBy();
return $this;
}
foreach ($queryPartNames as $queryPartName) {
$this->resetQueryPart($queryPartName);
}
return $this;
}
@@ -1129,9 +1174,16 @@ class QueryBuilder implements IQueryBuilder {
* @param string $queryPartName
*
* @return $this This QueryBuilder instance.
* @since 30.0.0 Only 'where'|'having'|'groupBy'|'orderBy' are supported. Everything else will throw.
*/
public function resetQueryPart($queryPartName) {
$this->queryBuilder->resetQueryPart($queryPartName);
match ($queryPartName) {
'where' => $this->queryBuilder->resetWhere(),
'having' => $this->queryBuilder->resetHaving(),
'groupBy' => $this->queryBuilder->resetGroupBy(),
'orderBy' => $this->queryBuilder->resetOrderBy(),
default => throw new \Exception('Resetting query part "' . $queryPartName. '" is no longer supported. Please create a new QueryBuilder instead.'),
};
return $this;
}
@@ -1166,7 +1218,7 @@ class QueryBuilder implements IQueryBuilder {
* @return IParameter the placeholder name used.
*/
public function createNamedParameter($value, $type = IQueryBuilder::PARAM_STR, $placeHolder = null) {
return new Parameter($this->queryBuilder->createNamedParameter($value, $type, $placeHolder));
return new Parameter($this->queryBuilder->createNamedParameter($value, $this->convertParameterTypeToDoctrine($type), $placeHolder));
}
/**
@@ -1192,7 +1244,7 @@ class QueryBuilder implements IQueryBuilder {
* @return IParameter
*/
public function createPositionalParameter($value, $type = IQueryBuilder::PARAM_STR) {
return new Parameter($this->queryBuilder->createPositionalParameter($value, $type));
return new Parameter($this->queryBuilder->createPositionalParameter($value, $this->convertParameterTypeToDoctrine($type)));
}
/**
@@ -1248,7 +1300,7 @@ class QueryBuilder implements IQueryBuilder {
* @throws \BadMethodCallException When being called before an insert query has been run.
*/
public function getLastInsertId(): int {
if ($this->getType() === \Doctrine\DBAL\Query\QueryBuilder::INSERT && $this->lastInsertedTable) {
if ($this->getType() === self::INSERT && $this->lastInsertedTable) {
// lastInsertId() needs the prefix but no quotes
$table = $this->prefixTableName($this->lastInsertedTable);
return $this->connection->lastInsertId($table);

View File

@@ -30,14 +30,21 @@ class ResultAdapter implements IResult {
}
public function fetch(int $fetchMode = PDO::FETCH_ASSOC) {
return $this->inner->fetch($fetchMode);
return match ($fetchMode) {
PDO::FETCH_ASSOC => $this->inner->fetchAssociative(),
PDO::FETCH_NUM => $this->inner->fetchNumeric(),
PDO::FETCH_COLUMN => $this->inner->fetchOne(),
default => throw new \Exception('Fetch mode needs to be assoc, num or column.'),
};
}
public function fetchAll(int $fetchMode = PDO::FETCH_ASSOC): array {
if ($fetchMode !== PDO::FETCH_ASSOC && $fetchMode !== PDO::FETCH_NUM && $fetchMode !== PDO::FETCH_COLUMN) {
throw new \Exception('Fetch mode needs to be assoc, num or column.');
}
return $this->inner->fetchAll($fetchMode);
return match ($fetchMode) {
PDO::FETCH_ASSOC => $this->inner->fetchAllAssociative(),
PDO::FETCH_NUM => $this->inner->fetchAllNumeric(),
PDO::FETCH_COLUMN => $this->inner->fetchFirstColumn(),
default => throw new \Exception('Fetch mode needs to be assoc, num or column.'),
};
}
public function fetchColumn($columnIndex = 0) {
@@ -49,6 +56,6 @@ class ResultAdapter implements IResult {
}
public function rowCount(): int {
return $this->inner->rowCount();
return (int) $this->inner->rowCount();
}
}

View File

@@ -19,8 +19,8 @@ class SQLiteMigrator extends Migrator {
foreach ($targetSchema->getTables() as $table) {
foreach ($table->getColumns() as $column) {
// column comments are not supported on SQLite
if ($column->getComment() !== null) {
$column->setComment(null);
if ($column->getComment() !== '') {
$column->setComment('');
}
}
}

View File

@@ -1,53 +0,0 @@
<?php
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\DB;
use Doctrine\Common\EventSubscriber;
use Doctrine\DBAL\Event\ConnectionEventArgs;
use Doctrine\DBAL\Events;
class SQLiteSessionInit implements EventSubscriber {
/**
* @var bool
*/
private $caseSensitiveLike;
/**
* @var string
*/
private $journalMode;
/**
* Configure case sensitive like for each connection
*
* @param bool $caseSensitiveLike
* @param string $journalMode
*/
public function __construct($caseSensitiveLike, $journalMode) {
$this->caseSensitiveLike = $caseSensitiveLike;
$this->journalMode = $journalMode;
}
/**
* @param ConnectionEventArgs $args
* @return void
*/
public function postConnect(ConnectionEventArgs $args) {
$sensitive = $this->caseSensitiveLike ? 'true' : 'false';
$args->getConnection()->executeUpdate('PRAGMA case_sensitive_like = ' . $sensitive);
$args->getConnection()->executeUpdate('PRAGMA journal_mode = ' . $this->journalMode);
/** @var \Doctrine\DBAL\Driver\PDO\Connection $connection */
$connection = $args->getConnection()->getWrappedConnection();
$pdo = $connection->getWrappedConnection();
$pdo->sqliteCreateFunction('md5', 'md5', 1);
}
public function getSubscribedEvents() {
return [Events::postConnect];
}
}

View File

@@ -8,6 +8,7 @@ namespace OC\DB;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\Table;
use OCP\DB\ISchemaWrapper;
class SchemaWrapper implements ISchemaWrapper {
@@ -43,26 +44,25 @@ class SchemaWrapper implements ISchemaWrapper {
/**
* Gets all table names
*
* @return array
* @return list<string>
*/
public function getTableNamesWithoutPrefix() {
$tableNames = $this->schema->getTableNames();
return array_map(function ($tableName) {
public function getTableNamesWithoutPrefix(): array {
return array_map(function (string $tableName) {
if (str_starts_with($tableName, $this->connection->getPrefix())) {
return substr($tableName, strlen($this->connection->getPrefix()));
}
return $tableName;
}, $tableNames);
}, $this->getTableNames());
}
// Overwritten methods
/**
* @return array
* @return list<string>
*/
public function getTableNames() {
return $this->schema->getTableNames();
public function getTableNames(): array {
return array_map(static fn (Table $table) => $table->getName(), $this->schema->getTables());
}
/**

View File

@@ -1,36 +0,0 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\DB;
use Doctrine\Common\EventSubscriber;
use Doctrine\DBAL\Connections\PrimaryReadReplicaConnection;
use Doctrine\DBAL\Event\ConnectionEventArgs;
use Doctrine\DBAL\Events;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\TransactionIsolationLevel;
class SetTransactionIsolationLevel implements EventSubscriber {
/**
* @param ConnectionEventArgs $args
* @return void
*/
public function postConnect(ConnectionEventArgs $args) {
$connection = $args->getConnection();
if ($connection instanceof PrimaryReadReplicaConnection && $connection->isConnectedToPrimary()) {
$connection->setTransactionIsolation(TransactionIsolationLevel::READ_COMMITTED);
if ($connection->getDatabasePlatform() instanceof MySQLPlatform) {
$connection->executeStatement('SET SESSION AUTOCOMMIT=1');
}
}
}
public function getSubscribedEvents() {
return [Events::postConnect];
}
}

Some files were not shown because too many files have changed in this diff Show More