Merge branch 'master' into refactor/OC-Server-getRootFolder

Signed-off-by: John Molakvoæ <skjnldsv@users.noreply.github.com>
pull/40123/head
John Molakvoæ 2 months ago committed by GitHub
commit 3f560ae940
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

File diff suppressed because it is too large Load Diff

10
.github/CODEOWNERS vendored

@ -28,7 +28,15 @@
/apps/weather_status/appinfo/info.xml @julien-nc @juliushaertl
/apps/workflowengine/appinfo/info.xml @blizzz @juliushaertl
# Frontend expertise
/apps/files/src* @skjnldsv
/apps/files_external/src* @skjnldsv
/apps/files_reminders/src* @skjnldsv
/apps/files_sharing/src/actions* @skjnldsv
/apps/files_trashbin/src* @skjnldsv
# Security team
/resources/codesigning @mgallien @miaulalala @nickvergessen
/resources/config/ca-bundle.crt @ChristophWurst @miaulalala @nickvergessen
/.drone.yml @nickvergessen
@ -43,7 +51,7 @@
/core/routes.php @Altahrim
# OpenAPI
openapi.json @provokateurin
openapi*.json @provokateurin
ResponseDefinitions.php @provokateurin
# Talk team

@ -29,6 +29,13 @@ Thanks for wanting to contribute source code to Nextcloud. That's great!
Please read the [Developer Manuals][devmanual] to learn how to create your first application or how to test the Nextcloud code with PHPUnit.
### Conventional Commits
Please use [Conventional Commits](https://www.conventionalcommits.org) for your commit messages. This helps maintain clarity and consistency across the project, making it easier to understand changes and automate versioning.
```
feat(files_sharing): allow sharing with contacts
```
### Tests
In order to constantly increase the quality of our software we can no longer accept pull request which submit un-tested code.
@ -44,9 +51,9 @@ their contribution under the project's license.
Please read [contribute/developer-certificate-of-origin][dcofile].
If you can certify it, then just add a line to every git commit message:
````
Signed-off-by: Random J Developer <random@developer.example.org>
````
```
Signed-off-by: Random J Developer <random@developer.example.org>
```
Use your real name (sorry, no pseudonyms or anonymous contributions).
If you set your `user.name` and `user.email` git configs, you can sign your

@ -101,10 +101,10 @@ body:
Select PHP engine version serving Nextcloud Server.
_Describe in the "Additional info" section if you chose "Other"._
options:
- "PHP 7.4"
- "PHP 8.0"
- "PHP 8.1"
- "PHP 8.2"
- "PHP 8.3"
- "Other"
- type: dropdown
id: webserver

@ -14,6 +14,49 @@ updates:
reviewers:
- "nextcloud/server-dependabot"
# cs-fixer
- package-ecosystem: composer
directory: "/vendor-bin/cs-fixer"
schedule:
interval: weekly
day: saturday
time: "04:10"
timezone: Europe/Copenhagen
labels:
- "3. to review"
- "feature: dependencies"
reviewers:
- "nextcloud/server-dependabot"
# openapi-extractor
- package-ecosystem: composer
directory: "/vendor-bin/openapi-extractor"
schedule:
interval: weekly
day: saturday
time: "04:20"
timezone: Europe/Brussels
labels:
- "3. to review"
- "feature: dependencies"
reviewers:
- "nextcloud/server-dependabot"
- "provokateurin"
# psalm
- package-ecosystem: composer
directory: "/vendor-bin/psalm"
schedule:
interval: weekly
day: saturday
time: "04:30"
timezone: Europe/Madrid
labels:
- "3. to review"
- "feature: dependencies"
reviewers:
- "nextcloud/server-dependabot"
# Main master npm
- package-ecosystem: npm
directory: "/"
@ -64,7 +107,7 @@ updates:
day: saturday
time: "03:00"
timezone: Europe/Paris
target-branch: stable25
target-branch: stable26
labels:
- "3. to review"
- "feature: dependencies"
@ -84,7 +127,7 @@ updates:
day: saturday
time: "03:00"
timezone: Europe/Paris
target-branch: stable26
target-branch: stable27
labels:
- "3. to review"
- "feature: dependencies"
@ -104,7 +147,7 @@ updates:
day: saturday
time: "03:00"
timezone: Europe/Paris
target-branch: stable27
target-branch: stable28
labels:
- "3. to review"
- "feature: dependencies"
@ -125,7 +168,7 @@ updates:
day: saturday
time: "03:00"
timezone: Europe/Paris
target-branch: stable25
target-branch: stable26
labels:
- "3. to review"
- "feature: dependencies"
@ -143,7 +186,7 @@ updates:
day: saturday
time: "03:00"
timezone: Europe/Paris
target-branch: stable26
target-branch: stable27
labels:
- "3. to review"
- "feature: dependencies"
@ -161,7 +204,7 @@ updates:
day: saturday
time: "03:00"
timezone: Europe/Paris
target-branch: stable27
target-branch: stable28
labels:
- "3. to review"
- "feature: dependencies"
@ -176,7 +219,15 @@ updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: weekly
day: saturday
time: "03:00"
interval: monthly
timezone: Europe/Paris
groups:
github-actions:
patterns:
- "*"
labels:
- "3. to review"
- "feature: dependencies"
reviewers:
- "nextcloud/server-dependabot"

@ -0,0 +1,96 @@
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@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
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@b4ffde65f46336ab88eb53be808477a3936bae11
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@7fdd3ece872ec7ec4c098ae5ab7637d5e0a96067 # v2
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

@ -20,7 +20,7 @@ jobs:
# Only run on stableXX branches
if: startsWith( github.base_ref, 'stable')
runs-on: ubuntu-latest
runs-on: ubuntu-latest-low
steps:
- name: Download updater config

@ -22,7 +22,7 @@ jobs:
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
runs-on: ubuntu-latest-low
steps:
- name: Download version.php from ${{ github.base_ref }}

@ -0,0 +1,31 @@
# 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
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@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: webiny/action-conventional-commits@8bc41ff4e7d423d56fa4905f6ff79209a78776c7 # v1.3.0
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

@ -15,15 +15,16 @@ jobs:
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@e591dbfe838300c007028e1219ca82cc26e8d7c5 # v2
uses: skjnldsv/check-actor-permission@69e92a3c4711150929bca9fcf34448c5bf5526e7 # v2
with:
require: write
- name: Add reaction on start
uses: peter-evans/create-or-update-comment@23ff15729ef2fc348714a3bb66d2f655ca9066f2 # v3.1.0
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
repository: ${{ github.event.repository.full_name }}
@ -31,7 +32,7 @@ jobs:
reactions: "+1"
- name: Parse command
uses: skjnldsv/parse-command-comment@7cef1df370a99dfd5bf896d50121390c96785db8 # v2
uses: skjnldsv/parse-command-comment@5c955203c52424151e6d0e58fb9de8a9f6a605a1 # v2
id: command
# Init path depending on which command is run
@ -39,9 +40,9 @@ jobs:
id: git-path
run: |
if ${{ startsWith(steps.command.outputs.arg1, '/') }}; then
echo "path=${{ github.workspace }}${{steps.command.outputs.arg1}}" >> $GITHUB_OUTPUT
echo "path=${{steps.command.outputs.arg1}}" >> $GITHUB_OUTPUT
else
echo "path=${{ github.workspace }}${{steps.command.outputs.arg2}}" >> $GITHUB_OUTPUT
echo "path=${{steps.command.outputs.arg2}}" >> $GITHUB_OUTPUT
fi
- name: Init branch
@ -54,13 +55,13 @@ jobs:
steps:
- name: Restore cached git repository
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
uses: buildjet/cache@e376f15c6ec6dc595375c78633174c7e5f92dc0e # v3
with:
path: .git
key: git-repo
- name: Checkout ${{ needs.init.outputs.head_ref }}
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v3.6.0
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
fetch-depth: 0
@ -76,16 +77,22 @@ jobs:
id: package-engines-versions
with:
fallbackNode: '^20'
fallbackNpm: '^9'
fallbackNpm: '^10'
- name: Set up node ${{ steps.package-engines-versions.outputs.nodeVersion }}
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
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:
@ -95,29 +102,36 @@ jobs:
npm ci
npm run build --if-present
- name: Commit and push default
if: ${{ needs.init.outputs.arg1 != 'fixup' && needs.init.outputs.arg1 != 'amend' }}
- name: Commit default
if: ${{ !contains(needs.init.outputs.arg1, 'fixup') && !contains(needs.init.outputs.arg1, 'amend') }}
run: |
git add ${{ needs.init.outputs.git_path }}
git add ${{ github.workspace }}${{ needs.init.outputs.git_path }}
git commit --signoff -m 'chore(assets): Recompile assets'
git push origin ${{ needs.init.outputs.head_ref }}
- name: Commit and push fixup
if: ${{ needs.init.outputs.arg1 == 'fixup' }}
- name: Commit fixup
if: ${{ contains(needs.init.outputs.arg1, 'fixup') }}
run: |
git add ${{ needs.init.outputs.git_path }}
git add ${{ github.workspace }}${{ needs.init.outputs.git_path }}
git commit --fixup=HEAD --signoff
git push origin ${{ needs.init.outputs.head_ref }}
- name: Commit and push amend
if: ${{ needs.init.outputs.arg1 == 'amend' }}
- name: Commit amend
if: ${{ contains(needs.init.outputs.arg1, 'amend') }}
run: |
git add ${{ needs.init.outputs.git_path }}
git add ${{ github.workspace }}${{ needs.init.outputs.git_path }}
git commit --amend --no-edit --signoff
git push --force origin ${{ needs.init.outputs.head_ref }}
# 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@23ff15729ef2fc348714a3bb66d2f655ca9066f2 # v3.1.0
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0
if: failure()
with:
token: ${{ secrets.COMMAND_BOT_PAT }}

@ -18,7 +18,7 @@ jobs:
steps:
- name: Add reaction on start
uses: peter-evans/create-or-update-comment@23ff15729ef2fc348714a3bb66d2f655ca9066f2 # v3.0.1
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v3.0.1
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
repository: ${{ github.event.repository.full_name }}
@ -51,7 +51,7 @@ jobs:
git push
- name: Add reaction on failure
uses: peter-evans/create-or-update-comment@23ff15729ef2fc348714a3bb66d2f655ca9066f2 # v3.0.1
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v3.0.1
if: failure()
with:
token: ${{ secrets.COMMAND_BOT_PAT }}

@ -23,7 +23,7 @@ jobs:
steps:
- name: Add reaction on start
uses: peter-evans/create-or-update-comment@23ff15729ef2fc348714a3bb66d2f655ca9066f2 # v3.0.1
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v3.0.1
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
repository: ${{ github.event.repository.full_name }}
@ -42,7 +42,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.COMMAND_BOT_PAT }}
- name: Add reaction on failure
uses: peter-evans/create-or-update-comment@23ff15729ef2fc348714a3bb66d2f655ca9066f2 # v3.0.1
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v3.0.1
if: failure()
with:
token: ${{ secrets.COMMAND_BOT_PAT }}

@ -31,7 +31,7 @@ jobs:
- name: Check composer.json
id: check_composer
uses: andstor/file-existence-action@20b4d2e596410855db8f9ca21e96fbe18e12930b # v2
uses: andstor/file-existence-action@076e0072799f4942c8bc574a82233e1e4d13e9d6 # v2
with:
files: "composer.json"
@ -47,7 +47,7 @@ jobs:
fallbackNpm: "^9"
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: ${{ steps.versions.outputs.nodeVersion }}
@ -77,10 +77,10 @@ jobs:
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]
containers: ["component", 0, 1, 2, 3, 4, 5]
# Hack as strategy.job-total includes the component and GitHub does not allow math expressions
# Always aling this number with the total of e2e runners (max. index + 1)
total-containers: [3]
total-containers: [6]
name: runner ${{ matrix.containers }}
@ -93,7 +93,7 @@ jobs:
path: ./
- name: Set up node ${{ needs.init.outputs.nodeVersion }}
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: ${{ needs.init.outputs.nodeVersion }}
@ -101,7 +101,7 @@ jobs:
run: npm i -g npm@"${{ needs.init.outputs.npmVersion }}"
- name: Run ${{ matrix.containers == 'component' && 'component' || 'E2E' }} cypress tests
uses: cypress-io/github-action@ebe8b24c4428922d0f793a5c4c96853a633180e3 # v6.6.0
uses: cypress-io/github-action@1b70233146622b69e789ccdd4f9452adc638d25a # v6.6.1
with:
component: ${{ matrix.containers == 'component' }}
group: ${{ matrix.use-cypress-cloud && matrix.containers == 'component' && 'Run component' || matrix.use-cypress-cloud && 'Run E2E' || '' }}
@ -121,7 +121,7 @@ jobs:
SPLIT_INDEX: ${{ matrix.containers == 'component' && 0 || matrix.containers }}
- name: Upload snapshots
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
if: always()
with:
name: snapshots_${{ matrix.containers }}
@ -132,7 +132,7 @@ jobs:
run: docker logs nextcloud-cypress-tests-${{ env.APP_NAME }} > nextcloud.log
- name: Upload NC logs
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
if: failure() && matrix.containers != 'component'
with:
name: nc_logs_${{ matrix.containers }}
@ -143,14 +143,14 @@ jobs:
run: docker exec nextcloud-cypress-tests-server tar -cvjf - data > data.tar
- name: Upload data dir archive
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
if: failure() && matrix.containers != 'component'
with:
name: nc_data_${{ matrix.containers }}
path: data.tar
summary:
runs-on: ubuntu-latest
runs-on: ubuntu-latest-low
needs: [init, cypress]
if: always()

@ -22,7 +22,7 @@ concurrency:
jobs:
auto-approve-merge:
if: github.actor == 'dependabot[bot]'
runs-on: ubuntu-latest
runs-on: ubuntu-latest-low
permissions:
# for hmarr/auto-approve-action to approve PRs
pull-requests: write

@ -1,29 +1,51 @@
name: FTP unit tests
name: PHPUnit files_external FTP
on:
pull_request:
paths:
- '.github/**'
- 'apps/files_external/**'
schedule:
- cron: "5 2 * * *"
concurrency:
group: ftp-${{ github.head_ref || github.run_id }}
group: files-external-ftp-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
env:
APP_NAME: files_external
jobs:
ftp-tests:
changes:
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
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' }}
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.0']
php-versions: ['8.0', '8.3']
ftpd: ['proftpd', 'vsftpd', 'pure-ftpd']
include:
- php-versions: '8.0'
coverage: ${{ github.event_name != 'pull_request' }}
name: php${{ matrix.php-versions }}-${{ matrix.ftpd }}
@ -42,11 +64,14 @@ jobs:
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@c5fc0d8281aba02c7fda07d3a70cc5371548067d #v2.25.2
with:
php-version: ${{ matrix.php-versions }}
extensions: mbstring, fileinfo, intl, sqlite, pdo_sqlite, zip, gd
# 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 }}
@ -55,8 +80,9 @@ jobs:
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 ${{ env.APP_NAME }}
php -S localhost:8080 &
./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"));'
@ -64,21 +90,30 @@ jobs:
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: |
echo "<?php return ['run' => true,'host' => 'localhost','user' => 'test','password' => 'test', 'root' => '${{ env.FTP_ROOT }}'];" > apps/${{ env.APP_NAME }}/tests/config.ftp.php
composer run test:files_external apps/files_external/tests/Storage/FtpTest.php
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
with:
files: ./clover.xml
flags: phpunit-files-external-ftp
- name: ftpd logs
if: always()
run: |
docker logs ftp
ftp-summary:
runs-on: ubuntu-latest
needs: ftp-tests
runs-on: ubuntu-latest-low
needs: [changes, files-external-ftp]
if: always()
steps:
- name: Summary status
run: if ${{ needs.ftp-tests.result != 'success' }}; then exit 1; fi
run: if ${{ needs.changes.outputs.src != 'false' && needs.files-external-ftp.result != 'success' }}; then exit 1; fi

@ -0,0 +1,185 @@
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@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
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.0', '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@b4ffde65f46336ab88eb53be808477a3936bae11
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@4bd44f22a98a19e0950cbad5f31095157cc9621b # v2
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
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.0', '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@b4ffde65f46336ab88eb53be808477a3936bae11
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@4bd44f22a98a19e0950cbad5f31095157cc9621b # v2
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
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

@ -0,0 +1,109 @@
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@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
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.0', '8.3']
sftpd: ['openssh']
include:
- php-versions: '8.0'
coverage: ${{ github.event_name != 'pull_request' }}
name: php${{ matrix.php-versions }}-${{ matrix.sftpd }}
steps:
- name: Checkout server
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
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@c5fc0d8281aba02c7fda07d3a70cc5371548067d #v2.25.2
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
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

@ -1,19 +1,41 @@
name: Samba Kerberos SSO
on:
pull_request:
paths:
- 'apps/files_external/**'
- '.github/workflows/smb-kerberos.yml'
schedule:
- cron: "5 2 * * *"
concurrency:
group: smb-kerberos-${{ github.head_ref || github.run_id }}
group: files-external-smb-kerberos-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
smb-kerberos-tests:
runs-on: ubuntu-latest
changes:
runs-on: ubuntu-latest-low
if: ${{ github.repository_owner != 'nextcloud-gmbh' }}
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
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
@ -22,11 +44,13 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
with:
submodules: true
- name: Checkout user_saml
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
with:
repository: nextcloud/user_saml
path: apps/user_saml
- name: Pull images
run: |
docker pull ghcr.io/icewind1991/samba-krb-test-dc
@ -35,21 +59,35 @@ jobs:
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: failure()
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

@ -0,0 +1,108 @@
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@0bc4621a3135347011ad047f9ecf449bf72ce2bd # v3.0.0
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.0', '8.3']
include:
- php-versions: '8.0'
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@b4ffde65f46336ab88eb53be808477a3936bae11
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@4bd44f22a98a19e0950cbad5f31095157cc9621b # v2
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@4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0 # v3.1.5
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

@ -0,0 +1,105 @@
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@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
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.0', '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@b4ffde65f46336ab88eb53be808477a3936bae11
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@4bd44f22a98a19e0950cbad5f31095157cc9621b # v2
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@ab904c41d6ece82784817410c45d8b8c02684457 # v3.1.6
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

@ -0,0 +1,93 @@
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@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
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.0', '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@b4ffde65f46336ab88eb53be808477a3936bae11
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@4bd44f22a98a19e0950cbad5f31095157cc9621b # v2
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
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

@ -24,7 +24,7 @@ jobs:
pull-requests: write
name: Block fixup and squash commits
runs-on: ubuntu-latest
runs-on: ubuntu-latest-low
steps:
- name: Run check

@ -0,0 +1,117 @@
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@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
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.0']
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@b4ffde65f46336ab88eb53be808477a3936bae11
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@4bd44f22a98a19e0950cbad5f31095157cc9621b # v2
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

@ -0,0 +1,166 @@
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@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
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@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Checkout Talk app
if: ${{ matrix.test-suite == 'videoverification_features' }}
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
repository: nextcloud/spreed
path: apps/spreed
ref: ${{ matrix.spreed-versions }}
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@c5fc0d8281aba02c7fda07d3a70cc5371548067d # v2
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

@ -20,13 +20,13 @@ concurrency:
jobs:
changes:
runs-on: ubuntu-latest
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
- uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
id: changes
continue-on-error: true
with:
@ -64,7 +64,7 @@ jobs:
fallbackNpm: '^9'
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: ${{ steps.versions.outputs.nodeVersion }}
@ -83,7 +83,7 @@ jobs:
summary:
permissions:
contents: none
runs-on: ubuntu-latest
runs-on: ubuntu-latest-low
needs: [changes, lint]
if: always()

@ -16,13 +16,13 @@ concurrency:
jobs:
changes:
runs-on: ubuntu-latest
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
- uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
id: changes
continue-on-error: true
with:
@ -65,7 +65,7 @@ jobs:
summary:
permissions:
contents: none
runs-on: ubuntu-latest
runs-on: ubuntu-latest-low
needs: [changes, lint]
if: always()

@ -17,13 +17,13 @@ concurrency:
jobs:
changes:
runs-on: ubuntu-latest
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
- uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
id: changes
continue-on-error: true
with:
@ -70,7 +70,7 @@ jobs:
summary:
permissions:
contents: none
runs-on: ubuntu-latest
runs-on: ubuntu-latest-low
needs: [changes, lint]
if: always()

@ -11,13 +11,13 @@ concurrency:
jobs:
changes:
runs-on: ubuntu-latest
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
- uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
id: changes
continue-on-error: true
with:
@ -72,7 +72,7 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- name: Set up node ${{ needs.versions.outputs.nodeVersion }}
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8
with:
node-version: ${{ needs.versions.outputs.nodeVersion }}
@ -89,7 +89,7 @@ jobs:
run: npm run test:coverage
- name: Collect coverage
uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4
uses: codecov/codecov-action@ab904c41d6ece82784817410c45d8b8c02684457 # v3.1.6
with:
files: ./coverage/lcov.info
@ -107,7 +107,7 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- name: Set up node ${{ needs.versions.outputs.nodeVersion }}
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8
with:
node-version: ${{ needs.versions.outputs.nodeVersion }}
@ -138,7 +138,7 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- name: Set up node ${{ needs.versions.outputs.nodeVersion }}
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8
with:
node-version: ${{ needs.versions.outputs.nodeVersion }}
@ -157,7 +157,7 @@ jobs:
summary:
permissions:
contents: none
runs-on: ubuntu-latest
runs-on: ubuntu-latest-low
needs: [changes, test, jsunit, handlebars]
if: always()

@ -17,13 +17,13 @@ concurrency:
jobs:
changes:
runs-on: ubuntu-latest
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
steps:
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
- uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
id: changes
continue-on-error: true
with:
@ -58,7 +58,7 @@ jobs:
fallbackNpm: '^9'
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: ${{ steps.versions.outputs.nodeVersion }}
@ -87,7 +87,7 @@ jobs:
summary:
permissions:
contents: none
runs-on: ubuntu-latest
runs-on: ubuntu-latest-low
needs: [changes, build]
if: always()

@ -18,7 +18,7 @@ jobs:
strategy:
fail-fast: false
matrix:
branches: ["main", "master", "stable27", "stable26", "stable25", "stable24"]
branches: ["main", "master", "stable28", "stable27", "stable26"]
name: npm-audit-fix-${{ matrix.branches }}
@ -36,7 +36,7 @@ jobs:
fallbackNpm: '^9'
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: ${{ steps.versions.outputs.nodeVersion }}
@ -58,7 +58,7 @@ jobs:
- name: Create Pull Request
if: always()
uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 # v5
uses: peter-evans/create-pull-request@a4f52f8033a6168103c2538976c07b467e8163bc # v5
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
commit-message: "chore(deps): fix npm audit"

@ -0,0 +1,125 @@
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@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
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.0', '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@b4ffde65f46336ab88eb53be808477a3936bae11
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@4bd44f22a98a19e0950cbad5f31095157cc9621b # v2
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
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

@ -0,0 +1,131 @@
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@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
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.0', '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@b4ffde65f46336ab88eb53be808477a3936bae11
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@4bd44f22a98a19e0950cbad5f31095157cc9621b # v2
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
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

@ -0,0 +1,121 @@
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@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
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.0', '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@b4ffde65f46336ab88eb53be808477a3936bae11
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@4bd44f22a98a19e0950cbad5f31095157cc9621b # v2
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
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

@ -45,8 +45,9 @@ jobs:
with:
blueprint: tests/blueprints/basic.toml
ref: ${{ github.event.pull_request.head.ref }}
- name: Run before measurements
uses: nextcloud/profiler@1e66a9de5f76a01e9d1db4f0153bcc1cbf989b3d
uses: nextcloud/profiler@6801ee10fc80f10b444388fb6ca9b36ad8a2ea83
with:
run: |
curl -s -X PROPFIND -u test:test http://localhost:8080/remote.php/dav/files/test
@ -68,7 +69,7 @@ jobs:
- name: Run after measurements
id: compare
uses: nextcloud/profiler@1e66a9de5f76a01e9d1db4f0153bcc1cbf989b3d
uses: nextcloud/profiler@6801ee10fc80f10b444388fb6ca9b36ad8a2ea83
with:
run: |
curl -s -X PROPFIND -u test:test http://localhost:8080/remote.php/dav/files/test
@ -82,14 +83,14 @@ jobs:
- name: Upload profiles
if: always()
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
with:
name: profiles
path: |
before.json
after.json
- uses: actions/github-script@v6
- uses: actions/github-script@v7
if: failure() && steps.compare.outcome == 'failure'
with:
github-token: ${{secrets.GITHUB_TOKEN}}

@ -0,0 +1,144 @@
# 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
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@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
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.0']
mariadb-versions: ['10.3', '10.4', '10.5', '10.6', '10.11']
include:
- php-versions: '8.3'
mariadb-versions: '10.6'
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="mysqladmin ping" --health-interval 5s --health-timeout 2s --health-retries 5
steps:
- name: Checkout server
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@4bd44f22a98a19e0950cbad5f31095157cc9621b # v2
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
with:
files: ./clover.db.xml
flags: phpunit-mariadb
- name: Print logs
if: always()
run: |
cat data/nextcloud.log
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

@ -0,0 +1,123 @@
# 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
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@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
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.0', '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@b4ffde65f46336ab88eb53be808477a3936bae11
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@7fdd3ece872ec7ec4c098ae5ab7637d5e0a96067 # v2
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
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

@ -0,0 +1,144 @@
# 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
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@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
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.0']
mysql-versions: ['8.0', '8.3']
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 5
steps:
- name: Checkout server
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@4bd44f22a98a19e0950cbad5f31095157cc9621b # v2
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
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

@ -0,0 +1,127 @@
# 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
# 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@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
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.0', '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@b4ffde65f46336ab88eb53be808477a3936bae11
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@7fdd3ece872ec7ec4c098ae5ab7637d5e0a96067 # v2
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
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

@ -2,6 +2,8 @@ name: PHPUnit oci
on:
pull_request:
schedule:
- cron: "5 2 * * *"
permissions:
contents: read
@ -12,13 +14,13 @@ concurrency:
jobs:
changes:
runs-on: ubuntu-latest
runs-on: ubuntu-latest-low
outputs:
src: ${{ steps.changes.outputs.src}}
src: ${{ steps.changes.outputs.src }}
steps:
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
- uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
id: changes
continue-on-error: true
with:
@ -26,36 +28,52 @@ jobs:
src:
- '.github/workflows/**'
- '3rdparty/**'
- '**/appinfo/**'
- '**/lib/**'
- '**/templates/**'
- '**/tests/**'
- '**/vendor-bin/**'
- 'vendor/**'
- 'vendor-bin/**'
- '.php-cs-fixer.dist.php'
- 'composer.json'
- 'composer.lock'
- '**.php'
phpunit-oci:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
if: ${{ github.repository_owner != 'nextcloud-gmbh' }}
needs: changes
if: needs.changes.outputs.src != 'false' && ${{ github.repository_owner != 'nextcloud-gmbh' }}
strategy:
matrix:
php-versions: ['8.0', '8.1', '8.2']
oracle-versions: ['11']
php-versions: ['8.0', '8.1', '8.2', '8.3']
include:
- php-versions: '8.3'
coverage: ${{ github.event_name != 'pull_request' }}
name: Oracle ${{ matrix.oracle-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
oracle:
image: ghcr.io/gvenzl/oracle-xe:11
image: ghcr.io/gvenzl/oracle-xe:${{ matrix.oracle-versions }}
# Provide passwords and other environment variables to container
env:
ORACLE_RANDOM_PASSWORD: true
APP_USER: autotest
APP_USER_PASSWORD: owncloud
APP_USER: oc_autotest
APP_USER_PASSWORD: nextcloud
# Forward Oracle port
ports:
- 1521:1521/tcp
- 4444:1521/tcp
# Provide healthcheck script options for startup
options: >-
@ -71,24 +89,38 @@ jobs:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@c5fc0d8281aba02c7fda07d3a70cc5371548067d #v2.25.2
uses: shivammathur/setup-php@4bd44f22a98a19e0950cbad5f31095157cc9621b # v2
with:
php-version: ${{ matrix.php-versions }}
extensions: ctype, curl, dom, fileinfo, gd, imagick, intl, json, mbstring, oci8, openssl, pcntl, pdo_sqlite, posix, sqlite, xml, zip
coverage: none
# 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, oci8
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: |
composer install
mkdir data
./occ maintenance:install --verbose --database=oci --database-name=XE --database-host=127.0.0.1 --database-port=1521 --database-user=autotest --database-pass=owncloud --admin-user admin --admin-pass admin
php -f index.php
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
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
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
with:
files: ./clover.db.xml
flags: phpunit-oci
- name: Run repair steps
run: |
@ -97,7 +129,7 @@ jobs:
summary:
permissions:
contents: none
runs-on: ubuntu-latest
runs-on: ubuntu-latest-low
needs: [changes, phpunit-oci]
if: always()

@ -0,0 +1,143 @@
# 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
name: PHPUnit pgsql
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@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
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.0']
# To keep the matrix smaller we ignore PostgreSQL '11', '13', '14' as we already test 10 and 15 as lower and upper bound
postgres-versions: ['10', '15', '16']
include:
- php-versions: '8.3'
postgres-versions: '15'
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@b4ffde65f46336ab88eb53be808477a3936bae11
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@4bd44f22a98a19e0950cbad5f31095157cc9621b # v2
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
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

@ -0,0 +1,127 @@
# 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
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@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1
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.0', '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@b4ffde65f46336ab88eb53be808477a3936bae11
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@7fdd3ece872ec7ec4c098ae5ab7637d5e0a96067 # v2
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
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

@ -1,130 +0,0 @@
name: S3 External storage
on:
pull_request:
paths:
- 'apps/files_external/**'
concurrency:
group: s3-external-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
env:
APP_NAME: files_external
jobs:
s3-external-tests-minio:
runs-on: ubuntu-latest
if: ${{ github.repository_owner != 'nextcloud-gmbh' }}
strategy:
# do not stop on another job's failure
fail-fast: false
matrix:
php-versions: ['8.0', '8.1']
name: php${{ matrix.php-versions }}-minio
services:
minio:
env:
MINIO_ACCESS_KEY: minio
MINIO_SECRET_KEY: minio123
image: bitnami/minio:2021.10.6
ports:
- "9000:9000"
steps:
- name: Checkout server
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@c5fc0d8281aba02c7fda07d3a70cc5371548067d #v2.25.2
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: |
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 ${{ env.APP_NAME }}
php -S localhost:8080 &
- name: PHPUnit
run: |
echo "<?php return ['run' => true, 'secret' => 'actually-not-secret', 'passwordsalt' => 'actually-not-secret', 'hostname' => 'localhost','key' => 'minio','secret' => 'minio123', 'bucket' => 'bucket', 'port' => 9000, 'use_ssl' => false, 'autocreate' => true, 'use_path_style' => true];" > apps/${{ env.APP_NAME }}/tests/config.amazons3.php
composer run test:files_external apps/files_external/tests/Storage/Amazons3Test.php
composer run test:files_external apps/files_external/tests/Storage/VersionedAmazonS3Test.php
- name: S3 logs
if: always()
run: |
docker ps -a
docker logs $(docker ps -aq)
s3-external-tests-localstack:
runs-on: ubuntu-latest
if: ${{ github.repository_owner != 'nextcloud-gmbh' }}
strategy:
# do not stop on another job's failure
fail-fast: false
matrix:
php-versions: ['8.0', '8.1']
name: php${{ matrix.php-versions }}-localstack
services:
minio:
env:
SERVICES: s3
DEBUG: 1
image: localstack/localstack:0.12.7
ports:
- "4566:4566"
steps:
- name: Checkout server
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@c5fc0d8281aba02c7fda07d3a70cc5371548067d #v2.25.2
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: |
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 ${{ env.APP_NAME }}
php -S localhost:8080 &
- name: PHPUnit
run: |
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/${{ env.APP_NAME }}/tests/config.amazons3.php
composer run test:files_external apps/files_external/tests/Storage/Amazons3Test.php
composer run test:files_external apps/files_external/tests/Storage/VersionedAmazonS3Test.php
- name: S3 logs
if: always()
run: |
docker ps -a
docker logs $(docker ps -aq)
s3-external-summary:
runs-on: ubuntu-latest
needs: [s3-external-tests-minio, s3-external-tests-localstack]
if: always()
steps:
- name: Summary status
run: if ${{ needs.s3-external-tests-minio.result != 'success' }} || ${{ needs.s3-external-tests-localstack.result != 'success' }}; then exit 1; fi

@ -1,95 +0,0 @@
name: S3 primary storage integration tests
on:
pull_request:
paths:
- '.github/workflows/**'
- '3rdparty/**'
- '**/*.php'
- '**/lib/**'
- '**/tests/**'
- '**/vendor-bin/**'
- '.php-cs-fixer.dist.php'
- 'composer.json'
- 'composer.lock'
concurrency:
group: s3-external-integration-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
s3-primary-integration-tests-minio:
runs-on: ubuntu-20.04
if: ${{ github.repository_owner != 'nextcloud-gmbh' }}
strategy:
# do not stop on another job's failure
fail-fast: false
matrix:
php-versions: ['8.0']
key: ['objectstore', 'objectstore_multibucket']
name: php${{ matrix.php-versions }}-${{ matrix.key }}-minio
services:
redis:
image: redis
ports:
- "6379:6379"
minio:
env:
MINIO_ACCESS_KEY: minio
MINIO_SECRET_KEY: minio123
image: bitnami/minio:2021.12.29
ports:
- "9000:9000"
steps:
- name: Checkout server
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@c5fc0d8281aba02c7fda07d3a70cc5371548067d #v2.25.2
with:
php-version: ${{ matrix.php-versions }}
extensions: mbstring, fileinfo, intl, sqlite, pdo_sqlite, zip, gd, redis
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" => "minio", "secret" => "minio123", "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" 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:
runs-on: ubuntu-latest
needs: [s3-primary-integration-tests-minio]
if: always()
steps:
- name: Summary status
run: if ${{ needs.s3-primary-integration-tests-minio.result != 'success' }}; then exit 1; fi

@ -1,87 +0,0 @@
name: S3 primary storage
on:
pull_request:
paths:
- '.github/workflows/**'
- '3rdparty/**'
- '**/*.php'
- '**/lib/**'
- '**/tests/**'
- '**/vendor-bin/**'
- '.php-cs-fixer.dist.php'
- 'composer.json'
- 'composer.lock'
concurrency:
group: s3-primary-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
s3-primary-tests-minio:
runs-on: ubuntu-20.04
if: ${{ github.repository_owner != 'nextcloud-gmbh' }}
strategy:
# do not stop on another job's failure
fail-fast: false
matrix:
php-versions: ['8.0']
key: ['objectstore', 'objectstore_multibucket']
name: php${{ matrix.php-versions }}-${{ matrix.key }}-minio
services:
minio:
env:
MINIO_ACCESS_KEY: minio
MINIO_SECRET_KEY: minio123
image: bitnami/minio:2021.12.29
ports:
- "9000:9000"
steps:
- name: Checkout server
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
with:
submodules: true
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@c5fc0d8281aba02c7fda07d3a70cc5371548067d #v2.25.2
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: |
composer install
mkdir data
echo '<?php $CONFIG=["${{ matrix.key }}" => ["class" => "OC\Files\ObjectStore\S3", "arguments" => ["bucket" => "nextcloud", "autocreate" => true, "key" => "minio", "secret" => "minio123", "hostname" => "localhost", "port" => 9000, "use_ssl" => false, "use_path_style" => true, "uploadPartSize" => 52428800]]];' > 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 index.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:db
- name: S3 logs
if: always()
run: |
docker ps -a
docker logs $(docker ps -aq)
s3-primary-summary:
runs-on: ubuntu-latest
needs: [s3-primary-tests-minio]
if: always()
steps:
- name: Summary status
run: if ${{ needs.s3-primary-tests-minio.result != 'success' }}; then exit 1; fi

@ -1,73 +0,0 @@
name: SFTP unit tests
on:
pull_request:
paths:
- 'apps/files_external/**'
env:
APP_NAME: files_external
concurrency:
group: sftp-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
sftp-tests:
runs-on: ubuntu-latest
if: ${{ github.repository_owner != 'nextcloud-gmbh' }}
strategy:
# do not stop on another job's failure
fail-fast: false
matrix:
php-versions: ['8.0']
sftpd: ['openssh']
name: php${{ matrix.php-versions }}-${{ matrix.sftpd }}
steps:
- name: Checkout server
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
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@c5fc0d8281aba02c7fda07d3a70cc5371548067d #v2.25.2
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: |
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 ${{ env.APP_NAME }}
php -S localhost:8080 &
- name: PHPUnit
run: |
echo "<?php return ['run' => true, 'host' => 'localhost:2222','user' => 'test','password' => 'test', 'root' => 'data'];" > apps/${{ env.APP_NAME }}/tests/config.sftp.php
composer run test:files_external apps/files_external/tests/Storage/SftpTest.php
- name: sftpd logs
if: always()
run: |
ls -l /tmp/sftp
docker logs sftp
sftp-summary:
runs-on: ubuntu-latest
needs: sftp-tests
if: always()
steps:
- name: Summary status
run: if ${{ needs.sftp-tests.result != 'success' }}; then exit 1; fi

@ -15,7 +15,7 @@ jobs:
issues: write
steps:
- uses: actions/stale@v8
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.COMMAND_BOT_PAT }}
stale-issue-message: >

@ -40,7 +40,7 @@ jobs:
- name: Upload Analysis results to GitHub
if: always()
uses: github/codeql-action/upload-sarif@v2
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
@ -68,7 +68,7 @@ jobs:
- name: Upload Security Analysis results to GitHub
if: always()
uses: github/codeql-action/upload-sarif@v2
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif

@ -12,7 +12,7 @@ jobs:
strategy:
fail-fast: false
matrix:
branches: ["master", "stable27", "stable26", "stable25", "stable24", "stable23", "stable22"]
branches: ["master", "stable28", "stable27", "stable26", "stable25", "stable24", "stable23", "stable22"]
name: update-ca-certificate-bundle-${{ matrix.branches }}
@ -26,7 +26,7 @@ jobs:
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@153407881ec5c347639a548ade7d8ad1d6740e38
uses: peter-evans/create-pull-request@a4f52f8033a6168103c2538976c07b467e8163bc
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
commit-message: "fix(security): Update CA certificate bundle"
@ -40,3 +40,4 @@ jobs:
labels: |
dependencies
3. to review
reviewers: ChristophWurst, miaulalala, nickvergessen

@ -0,0 +1,46 @@
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", "stable28", "stable27", "stable26", "stable25", "stable24", "stable23", "stable22"]
name: update-code-signing-crl-${{ matrix.branches }}
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
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@a4f52f8033a6168103c2538976c07b467e8163bc
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

@ -14,7 +14,7 @@ jobs:
strategy:
fail-fast: false
matrix:
branches: ["master", "stable27", "stable26", "stable25"]
branches: ["master", "stable28", "stable27", "stable26"]
name: update-psalm-baseline-${{ matrix.branches }}
@ -28,7 +28,7 @@ jobs:
uses: shivammathur/setup-php@v2
with:
php-version: '8.0'
extensions: ctype,curl,dom,fileinfo,gd,intl,json,mbstring,openssl,pdo_sqlite,posix,sqlite,xml,zip
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 }}
@ -37,11 +37,11 @@ jobs:
run: composer install
- name: Psalm
run: composer run psalm -- --monochrome --no-progress --output-format=text --update-baseline
run: composer run psalm:ci -- --monochrome --no-progress --output-format=text --update-baseline
continue-on-error: true
- name: Psalm OCP
run: composer run psalm -- -c psalm-ocp.xml --monochrome --no-progress --output-format=github --update-baseline
run: composer run psalm:ci -- -c psalm-ocp.xml --monochrome --no-progress --output-format=github --update-baseline
continue-on-error: true
- name: Reset composer
@ -50,7 +50,7 @@ jobs:
git checkout composer.json composer.lock lib/composer
- name: Create Pull Request
uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38
uses: peter-evans/create-pull-request@a4f52f8033a6168103c2538976c07b467e8163bc
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
commit-message: Update psalm baseline

4
.gitignore vendored

@ -129,6 +129,8 @@ nbproject
/build/bin
/build/lib/
/build/jsdocs/
/build/integration/output/
/build/integration/phpserver.log
/npm-debug.log
/PhantomJS_*
@ -162,6 +164,7 @@ tests/acceptance/vendor/
composer.phar
/lib/composer/bin
/lib/composer/bamarni
/vendor-bin/**/vendor
./.htaccess
@ -170,3 +173,4 @@ core/js/mimetypelist.js
# Tests - cypress
cypress/snapshots
cypress/videos
cypress/downloads

@ -94,5 +94,19 @@
RewriteRule ^(?:\.(?!well-known)|autotest|occ|issue|indie|db_|console).* - [R=404,L]
</IfModule>
# Clients like xDavv5 on Android, or Cyberduck, use chunked requests.
# When FastCGI or FPM is used with apache, requests arrive to Nextcloud without any content.
# This leads to the creation of empty files.
# The following directive will force the problematic requests to be buffered before being forwarded to Nextcloud.
# This way, the "Transfer-Encoding" header is removed, the "Content-Length" header is set, and the request content is proxied to Nextcloud.
# Here are more information about the issue:
# - https://docs.cyberduck.io/mountainduck/issues/fastcgi/
# - https://docs.nextcloud.com/server/latest/admin_manual/issues/general_troubleshooting.html#troubleshooting-webdav
<IfModule setenvif.c>
<Location "/remote.php">
SetEnvIf Transfer-Encoding "chunked" proxy-sendcl=1
</Location>
</IfModule>
AddDefaultCharset utf-8
Options -Indexes

@ -20,6 +20,7 @@ $config
->notPath('composer')
->notPath('node_modules')
->notPath('vendor')
->in('apps')
->in(__DIR__);
// Ignore additional app directories

@ -1 +1 @@
Subproject commit e6c45c6c0d4f92ffec621446fcc3b34584772b13
Subproject commit e8a165a3811f1b454694337aaff47c30888ca9fc

@ -1,14 +1,14 @@
# Security Policy
[Security](https://nextcloud.com/security/) is very important to us.
[Security](https://nextcloud.com/security/) is very important to us.
If you believe you have found a security vulnerability that meets our definition of a security
If you believe you have found a security vulnerability that meets our definition of a security
vulnerability, please report is as described below.
## Context
Please review our [threat model and accepted risks](https://nextcloud.com/security/threat-model) to learn what
is currently considered a security vulnerability versus expected behavior. And review what is considered
Please review our [threat model and accepted risks](https://nextcloud.com/security/threat-model) to learn what
is currently considered a security vulnerability versus expected behavior. And review what is considered
[in scope or bounty eligible](https://hackerone.com/nextcloud/policy_scopes).
@ -31,13 +31,17 @@ Your report should include:
You should receive an initial acknowledgement within 24 hours in most cases.
A member of the security team will confirm the vulnerability, determine its impact, follow-up with any questions,
A member of the security team will confirm the vulnerability, determine its impact, follow-up with any questions,
and coordinate the fix and publication.
The fix will be applied to all applicable and still supported stable branches, tested, and packaged in the next security release.
The vulnerability will be publicly announced after the release. Finally, your name will be added
to the [hall of fame](https://hackerone.com/nextcloud/thanks) as a thank you from the entire Nextcloud
community.
to the [hall of fame](https://hackerone.com/nextcloud/thanks) as a thank you from the entire Nextcloud
community.
If the vulnerability involves an app that is not maintained by Nextcloud (i.e. hosted by the
Nextcloud project but community maintained, or hosted elsewhere), the security team will try to coordinate with the
current maintainer and help to get the issue fixed in similar fashion.
### Bug Bounties
@ -47,8 +51,7 @@ on past bounty ranges can be found at [hackerone.com/nextcloud](https://hackeron
## Existing Security Advisories
Published security advisories for the Nextcloud Server, Clients and Apps can be viewed at
[https://github.com/nextcloud/security-advisories/security/advisories](https://github.com/nextcloud/security-advisories/security/advisories
).
[https://github.com/nextcloud/security-advisories/security/advisories](https://github.com/nextcloud/security-advisories/security/advisories).
## Supported Versions

@ -5,7 +5,7 @@
<name>Auditing / Logging</name>
<summary>Provides logging abilities for Nextcloud such as logging file accesses or otherwise sensitive actions.</summary>
<description>Provides logging abilities for Nextcloud such as logging file accesses or otherwise sensitive actions.</description>
<version>1.18.0</version>
<version>1.19.0</version>
<licence>agpl</licence>
<author>Nextcloud</author>
<namespace>AdminAudit</namespace>
@ -15,7 +15,7 @@
<category>monitoring</category>
<bugs>https://github.com/nextcloud/server/issues</bugs>
<dependencies>
<nextcloud min-version="28" max-version="28"/>
<nextcloud min-version="29" max-version="29"/>
</dependencies>
<background-jobs>
<job>OCA\AdminAudit\BackgroundJobs\Rotate</job>

@ -1,7 +1,7 @@
OC.L10N.register(
"admin_audit",
{
"Auditing / Logging" : "التدقيق / السجلات",
"Provides logging abilities for Nextcloud such as logging file accesses or otherwise sensitive actions." : "خاصية سجلات المراقبة لـ نكست كلاود مثل الوصول إلى سجلات الملفات أو المعلومات الحساسة الاخرى."
"Auditing / Logging" : "المراجعة / السجلات",
"Provides logging abilities for Nextcloud such as logging file accesses or otherwise sensitive actions." : "تُوفِّر إمكانيات تسجيل و مراجعة سجل الحركات على نكست كلاود."
},
"nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;");

@ -1,5 +1,5 @@
{ "translations": {
"Auditing / Logging" : "التدقيق / السجلات",
"Provides logging abilities for Nextcloud such as logging file accesses or otherwise sensitive actions." : "خاصية سجلات المراقبة لـ نكست كلاود مثل الوصول إلى سجلات الملفات أو المعلومات الحساسة الاخرى."
"Auditing / Logging" : "المراجعة / السجلات",
"Provides logging abilities for Nextcloud such as logging file accesses or otherwise sensitive actions." : "تُوفِّر إمكانيات تسجيل و مراجعة سجل الحركات على نكست كلاود."
},"pluralForm" :"nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;"
}

@ -0,0 +1,7 @@
OC.L10N.register(
"admin_audit",
{
"Auditing / Logging" : "Audit / Giriş",
"Provides logging abilities for Nextcloud such as logging file accesses or otherwise sensitive actions." : "Nextcloud üçün fayl girişləri və ya başqa həssas hərəkətlər kimi giriş imkanlarını təmin edir."
},
"nplurals=2; plural=(n != 1);");

@ -0,0 +1,5 @@
{ "translations": {
"Auditing / Logging" : "Audit / Giriş",
"Provides logging abilities for Nextcloud such as logging file accesses or otherwise sensitive actions." : "Nextcloud üçün fayl girişləri və ya başqa həssas hərəkətlər kimi giriş imkanlarını təmin edir."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}

@ -1,7 +1,7 @@
OC.L10N.register(
"admin_audit",
{
"Auditing / Logging" : "Auditieren / Protokollieren",
"Auditing / Logging" : "Auditieren/Protokollieren",
"Provides logging abilities for Nextcloud such as logging file accesses or otherwise sensitive actions." : "Stellt Protokollierungsfunktionen für Nextcloud zur Verfügung wie Dateizugriffe oder andere vertrauliche Aktionen."
},
"nplurals=2; plural=(n != 1);");

@ -1,5 +1,5 @@
{ "translations": {
"Auditing / Logging" : "Auditieren / Protokollieren",
"Auditing / Logging" : "Auditieren/Protokollieren",
"Provides logging abilities for Nextcloud such as logging file accesses or otherwise sensitive actions." : "Stellt Protokollierungsfunktionen für Nextcloud zur Verfügung wie Dateizugriffe oder andere vertrauliche Aktionen."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}

@ -4,4 +4,4 @@ OC.L10N.register(
"Auditing / Logging" : "פיקוח / תיעוד",
"Provides logging abilities for Nextcloud such as logging file accesses or otherwise sensitive actions." : "מספק יכולות תיעוד ל־Nextcloud כגון תיעוד גישה ליומן התיעוד או פעולות רגישות אחרות."
},
"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;");
"nplurals=3; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: 2;");

@ -1,5 +1,5 @@
{ "translations": {
"Auditing / Logging" : "פיקוח / תיעוד",
"Provides logging abilities for Nextcloud such as logging file accesses or otherwise sensitive actions." : "מספק יכולות תיעוד ל־Nextcloud כגון תיעוד גישה ליומן התיעוד או פעולות רגישות אחרות."
},"pluralForm" :"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;"
},"pluralForm" :"nplurals=3; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: 2;"
}

@ -0,0 +1,7 @@
OC.L10N.register(
"admin_audit",
{
"Auditing / Logging" : "Eftirlit / Atvikaskráning",
"Provides logging abilities for Nextcloud such as logging file accesses or otherwise sensitive actions." : "Býður upp á atvikaskráningu fyrir Nextcloud, eins og að skrá aðgang að skrám og fleiri viðkvæmar aðgerðir."
},
"nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);");

@ -0,0 +1,5 @@
{ "translations": {
"Auditing / Logging" : "Eftirlit / Atvikaskráning",
"Provides logging abilities for Nextcloud such as logging file accesses or otherwise sensitive actions." : "Býður upp á atvikaskráningu fyrir Nextcloud, eins og að skrá aðgang að skrám og fleiri viðkvæmar aðgerðir."
},"pluralForm" :"nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);"
}

@ -2,6 +2,6 @@ OC.L10N.register(
"admin_audit",
{
"Auditing / Logging" : "Auditoria / Registro",
"Provides logging abilities for Nextcloud such as logging file accesses or otherwise sensitive actions." : "Fornece recursos de registro para Nextcloud, como registros de acesso a arquivos ou outras ações sensíveis."
"Provides logging abilities for Nextcloud such as logging file accesses or otherwise sensitive actions." : "Fornece habilidades de registro para o NextCloud, como acessos de arquivo de log ou ações sensíveis."
},
"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");

@ -1,5 +1,5 @@
{ "translations": {
"Auditing / Logging" : "Auditoria / Registro",
"Provides logging abilities for Nextcloud such as logging file accesses or otherwise sensitive actions." : "Fornece recursos de registro para Nextcloud, como registros de acesso a arquivos ou outras ações sensíveis."
"Provides logging abilities for Nextcloud such as logging file accesses or otherwise sensitive actions." : "Fornece habilidades de registro para o NextCloud, como acessos de arquivo de log ou ações sensíveis."
},"pluralForm" :"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
}

@ -34,7 +34,8 @@ class Action {
public function __construct(
private IAuditLogger $logger,
) {}
) {
}
/**
* Log a single action with a log level of info
@ -45,9 +46,9 @@ class Action {
* @param bool $obfuscateParameters
*/
public function log(string $text,
array $params,
array $elements,
bool $obfuscateParameters = false): void {
array $params,
array $elements,
bool $obfuscateParameters = false): void {
foreach ($elements as $element) {
if (!isset($params[$element])) {
if ($obfuscateParameters) {

@ -29,7 +29,7 @@ namespace OCA\AdminAudit\Actions;
class Console extends Action {
/**
* @param $arguments
* @param array $arguments
*/
public function runCommand(array $arguments): void {
if (!isset($arguments[1]) || $arguments[1] === '_completion') {

@ -61,7 +61,7 @@ class UserManagement extends Action {
*/
public function assign(string $uid): void {
$this->log(
'UserID assigned: "%s"',
'UserID assigned: "%s"',
[ 'uid' => $uid ],
[ 'uid' ]
);

@ -70,7 +70,6 @@ use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
class Application extends App implements IBootstrap {
/** @var LoggerInterface */
protected $logger;
@ -101,7 +100,7 @@ class Application extends App implements IBootstrap {
* Register hooks in order to log them
*/
private function registerHooks(IAuditLogger $logger,
ContainerInterface $serverContainer): void {
ContainerInterface $serverContainer): void {
$this->userManagementHooks($logger, $serverContainer->get(IUserSession::class));
$this->groupHooks($logger, $serverContainer->get(IGroupManager::class));
$this->authHooks($logger);
@ -122,7 +121,7 @@ class Application extends App implements IBootstrap {
}
private function userManagementHooks(IAuditLogger $logger,
IUserSession $userSession): void {
IUserSession $userSession): void {
$userActions = new UserManagement($logger);
Util::connectHook('OC_User', 'post_createUser', $userActions, 'create');
@ -136,7 +135,7 @@ class Application extends App implements IBootstrap {
}
private function groupHooks(IAuditLogger $logger,
IGroupManager $groupManager): void {
IGroupManager $groupManager): void {
$groupActions = new GroupManagement($logger);
assert($groupManager instanceof GroupManager);
@ -167,7 +166,7 @@ class Application extends App implements IBootstrap {
}
private function appHooks(IAuditLogger $logger,
IEventDispatcher $eventDispatcher): void {
IEventDispatcher $eventDispatcher): void {
$eventDispatcher->addListener(ManagerEvent::EVENT_APP_ENABLE, function (ManagerEvent $event) use ($logger) {
$appActions = new AppManagement($logger);
$appActions->enableApp($event->getAppID());
@ -183,7 +182,7 @@ class Application extends App implements IBootstrap {
}
private function consoleHooks(IAuditLogger $logger,
IEventDispatcher $eventDispatcher): void {
IEventDispatcher $eventDispatcher): void {
$eventDispatcher->addListener(ConsoleEvent::class, function (ConsoleEvent $event) use ($logger) {
$appActions = new Console($logger);
$appActions->runCommand($event->getArguments());
@ -191,7 +190,7 @@ class Application extends App implements IBootstrap {
}
private function fileHooks(IAuditLogger $logger,
IEventDispatcher $eventDispatcher): void {
IEventDispatcher $eventDispatcher): void {
$fileActions = new Files($logger);
$eventDispatcher->addListener(
BeforePreviewFetchedEvent::class,
@ -264,7 +263,7 @@ class Application extends App implements IBootstrap {
}
private function securityHooks(IAuditLogger $logger,
IEventDispatcher $eventDispatcher): void {
IEventDispatcher $eventDispatcher): void {
$eventDispatcher->addListener(TwoFactorProviderChallengePassed::class, function (TwoFactorProviderChallengePassed $event) use ($logger) {
$security = new Security($logger);
$security->twofactorSuccess($event->getUser(), $event->getProvider());

@ -32,8 +32,7 @@ use Psr\Log\LoggerInterface;
*/
class AuditLogger implements IAuditLogger {
/** @var LoggerInterface */
private $parentLogger;
private LoggerInterface $parentLogger;
public function __construct(ILogFactory $logFactory, IConfig $config) {
$auditType = $config->getSystemValueString('log_type_audit', 'file');
@ -50,39 +49,39 @@ class AuditLogger implements IAuditLogger {
$this->parentLogger = $logFactory->getCustomPsrLogger($logFile, $auditType, $auditTag);
}
public function emergency($message, array $context = array()) {
public function emergency($message, array $context = array()): void {
$this->parentLogger->emergency($message, $context);
}
public function alert($message, array $context = array()) {
public function alert($message, array $context = array()): void {
$this->parentLogger->alert($message, $context);
}
public function critical($message, array $context = array()) {
public function critical($message, array $context = array()): void {
$this->parentLogger->critical($message, $context);
}
public function error($message, array $context = array()) {
public function error($message, array $context = array()): void {
$this->parentLogger->error($message, $context);
}
public function warning($message, array $context = array()) {
public function warning($message, array $context = array()): void {
$this->parentLogger->warning($message, $context);
}
public function notice($message, array $context = array()) {
public function notice($message, array $context = array()): void {
$this->parentLogger->notice($message, $context);
}
public function info($message, array $context = array()) {
public function info($message, array $context = array()): void {
$this->parentLogger->info($message, $context);
}
public function debug($message, array $context = array()) {
public function debug($message, array $context = array()): void {
$this->parentLogger->debug($message, $context);
}
public function log($level, $message, array $context = array()) {
public function log($level, $message, array $context = array()): void {
$this->parentLogger->log($level, $message, $context);
}
}

@ -27,8 +27,8 @@ declare(strict_types=1);
*/
namespace OCA\AdminAudit\BackgroundJobs;
use OCP\BackgroundJob\TimedJob;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\BackgroundJob\TimedJob;
use OCP\IConfig;
use OCP\Log\RotationTrait;

@ -30,6 +30,7 @@ use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\Log\Audit\CriticalActionPerformedEvent;
/** @template-implements IEventListener<CriticalActionPerformedEvent> */
class CriticalActionPerformedEventListener extends Action implements IEventListener {
public function handle(Event $event): void {
if (!($event instanceof CriticalActionPerformedEvent)) {

@ -30,17 +30,15 @@ use OCA\AdminAudit\Actions\Security;
use OCA\AdminAudit\AuditLogger;
use OCP\Authentication\TwoFactorAuth\IProvider;
use OCP\IUser;
use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class SecurityTest extends TestCase {
/** @var AuditLogger|\PHPUnit\Framework\MockObject\MockObject */
private $logger;
private AuditLogger|MockObject $logger;
/** @var Security */
private $security;
private Security $security;
/** @var IUser|\PHPUnit\Framework\MockObject\MockObject */
private $user;
private MockObject|IUser $user;
protected function setUp(): void {
parent::setUp();

@ -5,7 +5,7 @@
<name>Cloud Federation API</name>
<summary>Enable clouds to communicate with each other and exchange data</summary>
<description>The Cloud Federation API enables various Nextcloud instances to communicate with each other and to exchange data.</description>
<version>1.11.0</version>
<version>1.12.0</version>
<licence>agpl</licence>
<author>Bjoern Schiessle</author>
<namespace>CloudFederationAPI</namespace>
@ -15,6 +15,6 @@
<category>integration</category>
<bugs>https://github.com/nextcloud/server/issues</bugs>
<dependencies>
<nextcloud min-version="28" max-version="28"/>
<nextcloud min-version="29" max-version="29"/>
</dependencies>
</info>

@ -38,11 +38,11 @@ return [
'verb' => 'POST',
'root' => '/ocm',
],
// [
// 'name' => 'RequestHandler#inviteAccepted',
// 'url' => '/invite-accepted',
// 'verb' => 'POST',
// 'root' => '/ocm',
// ]
// [
// 'name' => 'RequestHandler#inviteAccepted',
// 'url' => '/invite-accepted',
// 'verb' => 'POST',
// 'root' => '/ocm',
// ]
],
];

@ -0,0 +1,8 @@
OC.L10N.register(
"cloud_federation_api",
{
"Cloud Federation API" : "API de Federación en la Nube",
"Enable clouds to communicate with each other and exchange data" : "Permitir que las nubes se comuniquen entre sí e intercambien datos",
"The Cloud Federation API enables various Nextcloud instances to communicate with each other and to exchange data." : "La API de Federación de Nubes permite que varias instancias de Nextcloud se comuniquen entre sí y intercambien datos."
},
"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");

@ -0,0 +1,6 @@
{ "translations": {
"Cloud Federation API" : "API de Federación en la Nube",
"Enable clouds to communicate with each other and exchange data" : "Permitir que las nubes se comuniquen entre sí e intercambien datos",
"The Cloud Federation API enables various Nextcloud instances to communicate with each other and to exchange data." : "La API de Federación de Nubes permite que varias instancias de Nextcloud se comuniquen entre sí y intercambien datos."
},"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
}

@ -0,0 +1,8 @@
OC.L10N.register(
"cloud_federation_api",
{
"Cloud Federation API" : "API de la federación en la nube",
"Enable clouds to communicate with each other and exchange data" : "Permitir que las nubes se comuniquen entre sí e intercambien datos",
"The Cloud Federation API enables various Nextcloud instances to communicate with each other and to exchange data." : "La API de la federación en la nube permite que varias instancias de Nextcloud se comuniquen entre sí e intercambien datos."
},
"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");

@ -0,0 +1,6 @@
{ "translations": {
"Cloud Federation API" : "API de la federación en la nube",
"Enable clouds to communicate with each other and exchange data" : "Permitir que las nubes se comuniquen entre sí e intercambien datos",
"The Cloud Federation API enables various Nextcloud instances to communicate with each other and to exchange data." : "La API de la federación en la nube permite que varias instancias de Nextcloud se comuniquen entre sí e intercambien datos."
},"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
}

@ -30,6 +30,7 @@ use OCA\CloudFederationAPI\Config;
use OCA\CloudFederationAPI\ResponseDefinitions;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\OpenAPI;
use OCP\AppFramework\Http\JSONResponse;
use OCP\Federation\Exceptions\ActionNotSupportedException;
use OCP\Federation\Exceptions\AuthenticationFailedException;
@ -55,6 +56,7 @@ use Psr\Log\LoggerInterface;
* @psalm-import-type CloudFederationAPIValidationError from ResponseDefinitions
* @psalm-import-type CloudFederationAPIError from ResponseDefinitions
*/
#[OpenAPI(scope: OpenAPI::SCOPE_FEDERATION)]
class RequestHandlerController extends Controller {
public function __construct(
string $appName,

@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**

@ -1,3 +0,0 @@
{
"directory": "js/vendor"
}

@ -1,3 +0,0 @@
# compiled vue templates
src/templates.js
js/

@ -5,7 +5,7 @@
<name>Comments</name>
<summary>Files app plugin to add comments to files</summary>
<description>Files app plugin to add comments to files</description>
<version>1.18.0</version>
<version>1.19.0</version>
<licence>agpl</licence>
<author>Arthur Schiwon</author>
<author>Vincent Petry</author>
@ -16,7 +16,7 @@
<category>social</category>
<bugs>https://github.com/nextcloud/server/issues</bugs>
<dependencies>
<nextcloud min-version="28" max-version="28"/>
<nextcloud min-version="29" max-version="29"/>
</dependencies>
<activity>

@ -15,7 +15,6 @@ OC.L10N.register(
"No comments yet, start the conversation!" : "Nog geen kommentaar, begin die gesprek!",
"Retry" : "Herprobeer",
"Comment" : "Kommentaar",
"%1$s commented" : "%1$s het kommentaar gelewer",
"_%n unread comment_::_%n unread comments_" : ["%n ongelese kommentaar","%n ongelese kommentare"]
},
"nplurals=2; plural=(n != 1);");

@ -13,7 +13,6 @@
"No comments yet, start the conversation!" : "Nog geen kommentaar, begin die gesprek!",
"Retry" : "Herprobeer",
"Comment" : "Kommentaar",
"%1$s commented" : "%1$s het kommentaar gelewer",
"_%n unread comment_::_%n unread comments_" : ["%n ongelese kommentaar","%n ongelese kommentare"]
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}

@ -9,14 +9,17 @@ OC.L10N.register(
"%1$s commented on %2$s" : "%1$s كتب تعليق على %2$s",
"{author} commented on {file}" : "{author} علّق على {file}",
"<strong>Comments</strong> for files" : "<strong>تعليقات</strong> على الملفات",
"You were mentioned on \"{file}\", in a comment by a user that has since been deleted" : "تمت الإشارة إليك في \"{file}\" في تعليق لمستخدم. لكن هذا المستخدم تم حذف حسابه بعدها",
"You were mentioned on \"{file}\", in a comment by an account that has since been deleted" : "تمت الإشارة إليك في \"{file}\"، في تعليقٍ من قِبَل حسابٍ تمّ حذفه سلفاً",
"{user} mentioned you in a comment on \"{file}\"" : "أشار إليك {user} في تعليق على {file}",
"Files app plugin to add comments to files" : "المكوِّن الإضافي لتطبيق الملفات لإضافة تعليقات إلى الملفات",
"Edit comment" : "تعديل التعليق",
"Delete comment" : "حذف التعليق",
"Cancel edit" : "إلغاء التعديل",
"New comment" : "ملاحظة جديدة",
"Write a comment …" : "أكتُب ملاحظةً ...",
"Post comment" : "أضف تعليق",
"\"@\" for mentions, \":\" for emoji, \"/\" for smart picker" : "\"@\" للإشارات, \":\" للإيموجي, \"/\" للاقط الذكي",
"@ for mentions, : for emoji, / for smart picker" : "@ للإشارات، : للإيموجي، / للاقط الذكي",
"Could not reload comments" : "تعذّرت إعادة تحميل الملاحظات",
"No comments yet, start the conversation!" : "لا يوجد تعليقات, ابدأ النقاش الآن!",
"No more messages" : "لامزيد من الرسائل",
"Retry" : "أعد المحاولة",
@ -28,7 +31,7 @@ OC.L10N.register(
"Comment deleted" : "التعليق حُذف",
"An error occurred while trying to delete the comment" : "حدث خطأ أثناء محاولة حذف التعليق",
"An error occurred while trying to create the comment" : "حدث خطأ أثناء محاولة إنشاء التعليق",
"%1$s commented" : "%1$s كتب تعليق",
"You were mentioned on \"{file}\", in a comment by a user that has since been deleted" : "تمت الإشارة إليك في \"{file}\" في تعليق لمستخدم. لكن هذا المستخدم تم حذف حسابه بعدها",
"_%n unread comment_::_%n unread comments_" : ["%n تعليق غير مقروء","%n تعليق غير مقروء","تعليقان غير مقروءة","%n تعليقات غير مقروء","%n تعليق غير مقروء","%n تعليق غير مقروء"]
},
"nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;");

@ -7,14 +7,17 @@
"%1$s commented on %2$s" : "%1$s كتب تعليق على %2$s",
"{author} commented on {file}" : "{author} علّق على {file}",
"<strong>Comments</strong> for files" : "<strong>تعليقات</strong> على الملفات",
"You were mentioned on \"{file}\", in a comment by a user that has since been deleted" : "تمت الإشارة إليك في \"{file}\" في تعليق لمستخدم. لكن هذا المستخدم تم حذف حسابه بعدها",
"You were mentioned on \"{file}\", in a comment by an account that has since been deleted" : "تمت الإشارة إليك في \"{file}\"، في تعليقٍ من قِبَل حسابٍ تمّ حذفه سلفاً",
"{user} mentioned you in a comment on \"{file}\"" : "أشار إليك {user} في تعليق على {file}",
"Files app plugin to add comments to files" : "المكوِّن الإضافي لتطبيق الملفات لإضافة تعليقات إلى الملفات",
"Edit comment" : "تعديل التعليق",
"Delete comment" : "حذف التعليق",
"Cancel edit" : "إلغاء التعديل",
"New comment" : "ملاحظة جديدة",
"Write a comment …" : "أكتُب ملاحظةً ...",
"Post comment" : "أضف تعليق",
"\"@\" for mentions, \":\" for emoji, \"/\" for smart picker" : "\"@\" للإشارات, \":\" للإيموجي, \"/\" للاقط الذكي",
"@ for mentions, : for emoji, / for smart picker" : "@ للإشارات، : للإيموجي، / للاقط الذكي",
"Could not reload comments" : "تعذّرت إعادة تحميل الملاحظات",
"No comments yet, start the conversation!" : "لا يوجد تعليقات, ابدأ النقاش الآن!",
"No more messages" : "لامزيد من الرسائل",
"Retry" : "أعد المحاولة",
@ -26,7 +29,7 @@
"Comment deleted" : "التعليق حُذف",
"An error occurred while trying to delete the comment" : "حدث خطأ أثناء محاولة حذف التعليق",
"An error occurred while trying to create the comment" : "حدث خطأ أثناء محاولة إنشاء التعليق",
"%1$s commented" : "%1$s كتب تعليق",
"You were mentioned on \"{file}\", in a comment by a user that has since been deleted" : "تمت الإشارة إليك في \"{file}\" في تعليق لمستخدم. لكن هذا المستخدم تم حذف حسابه بعدها",
"_%n unread comment_::_%n unread comments_" : ["%n تعليق غير مقروء","%n تعليق غير مقروء","تعليقان غير مقروءة","%n تعليقات غير مقروء","%n تعليق غير مقروء","%n تعليق غير مقروء"]
},"pluralForm" :"nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;"
}

@ -4,17 +4,33 @@ OC.L10N.register(
"Comments" : "Comentarios",
"You commented" : "Comentesti",
"{author} commented" : "{author} comentó",
"You commented on %1$s" : "Comentesti en %1$s",
"You commented on {file}" : "Comentesti en {file}",
"%1$s commented on %2$s" : "%1$s comentó en %2$s",
"{author} commented on {file}" : "{autor} comentó en {ficheru}",
"You commented on %1$s" : "Comentesti en: %1$s",
"You commented on {file}" : "Comentesti en: {file}",
"%1$s commented on %2$s" : "%1$s comentó en: %2$s",
"{author} commented on {file}" : "{author} comentó en: {file}",
"<strong>Comments</strong> for files" : "<strong>Comentarios</strong> pa ficheros",
"Edit comment" : "Editar comentariu",
"Delete comment" : "Desaniciar comentariu",
"No comments yet, start the conversation!" : "Entá nun hai comentarios. ¡Entama una conversación!",
"{user} mentioned you in a comment on \"{file}\"" : "{user} mentóte nun comentariu de: «{file}»",
"Files app plugin to add comments to files" : "Plugin de l'aplicación Ficheros p'amestar comentarios a los ficheros",
"Edit comment" : "Editar el comentariu",
"Delete comment" : "Desaniciar el comentariu",
"Cancel edit" : "Anular la edición",
"New comment" : "Comentariu nuevu",
"Write a comment …" : "Escribi un comentariu…",
"Post comment" : "Espublizar el comentariu",
"@ for mentions, : for emoji, / for smart picker" : "@ pa les menciones, : pa los fustaxes, / pal selector intelixente",
"Could not reload comments" : "Nun se pudieron recargar los comentarios",
"No comments yet, start the conversation!" : "Nun hai comentarios, ¡anicia una conversación!",
"No more messages" : "Nun hai más mensaxes",
"Retry" : "Retentar",
"_%n unread comment_::_%n unread comments_" : ["%n comentariu ensin lleer","%n comentarios ensin lleer"],
"Failed to mark comments as read" : "Nun se pudieron marcar los comentarios como lleíos",
"Unable to load the comments list" : "Nun ye posible cargar la llista de comentarios",
"_1 new comment_::_{unread} new comments_" : ["1 comentariu nuevu","{unread} comentarios nuevos"],
"Comment" : "Comentariu",
"%1$s commented" : "%1$s comentó"
"An error occurred while trying to edit the comment" : "Prodúxose un error mentanto se tentaba d'editar el comentariu",
"Comment deleted" : "Desanicióse'l comentariu",
"An error occurred while trying to delete the comment" : "Prodúxose un error mentanto se tentaba de desaniciar el comentariu",
"An error occurred while trying to create the comment" : "Prodúxose un error mentanto se tentaba de crear el comentariu",
"You were mentioned on \"{file}\", in a comment by a user that has since been deleted" : "Un usuariu que ta desaniciáu mentóte nun comentariu de: {file}",
"_%n unread comment_::_%n unread comments_" : ["%n comentariu ensin lleer","%n comentarios ensin lleer"]
},
"nplurals=2; plural=(n != 1);");

@ -2,17 +2,33 @@
"Comments" : "Comentarios",
"You commented" : "Comentesti",
"{author} commented" : "{author} comentó",
"You commented on %1$s" : "Comentesti en %1$s",
"You commented on {file}" : "Comentesti en {file}",
"%1$s commented on %2$s" : "%1$s comentó en %2$s",
"{author} commented on {file}" : "{autor} comentó en {ficheru}",
"You commented on %1$s" : "Comentesti en: %1$s",
"You commented on {file}" : "Comentesti en: {file}",
"%1$s commented on %2$s" : "%1$s comentó en: %2$s",
"{author} commented on {file}" : "{author} comentó en: {file}",
"<strong>Comments</strong> for files" : "<strong>Comentarios</strong> pa ficheros",
"Edit comment" : "Editar comentariu",
"Delete comment" : "Desaniciar comentariu",
"No comments yet, start the conversation!" : "Entá nun hai comentarios. ¡Entama una conversación!",
"{user} mentioned you in a comment on \"{file}\"" : "{user} mentóte nun comentariu de: «{file}»",
"Files app plugin to add comments to files" : "Plugin de l'aplicación Ficheros p'amestar comentarios a los ficheros",
"Edit comment" : "Editar el comentariu",
"Delete comment" : "Desaniciar el comentariu",
"Cancel edit" : "Anular la edición",
"New comment" : "Comentariu nuevu",
"Write a comment …" : "Escribi un comentariu…",
"Post comment" : "Espublizar el comentariu",
"@ for mentions, : for emoji, / for smart picker" : "@ pa les menciones, : pa los fustaxes, / pal selector intelixente",
"Could not reload comments" : "Nun se pudieron recargar los comentarios",
"No comments yet, start the conversation!" : "Nun hai comentarios, ¡anicia una conversación!",
"No more messages" : "Nun hai más mensaxes",
"Retry" : "Retentar",
"_%n unread comment_::_%n unread comments_" : ["%n comentariu ensin lleer","%n comentarios ensin lleer"],
"Failed to mark comments as read" : "Nun se pudieron marcar los comentarios como lleíos",
"Unable to load the comments list" : "Nun ye posible cargar la llista de comentarios",
"_1 new comment_::_{unread} new comments_" : ["1 comentariu nuevu","{unread} comentarios nuevos"],
"Comment" : "Comentariu",
"%1$s commented" : "%1$s comentó"
"An error occurred while trying to edit the comment" : "Prodúxose un error mentanto se tentaba d'editar el comentariu",
"Comment deleted" : "Desanicióse'l comentariu",
"An error occurred while trying to delete the comment" : "Prodúxose un error mentanto se tentaba de desaniciar el comentariu",
"An error occurred while trying to create the comment" : "Prodúxose un error mentanto se tentaba de crear el comentariu",
"You were mentioned on \"{file}\", in a comment by a user that has since been deleted" : "Un usuariu que ta desaniciáu mentóte nun comentariu de: {file}",
"_%n unread comment_::_%n unread comments_" : ["%n comentariu ensin lleer","%n comentarios ensin lleer"]
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}

@ -9,7 +9,6 @@ OC.L10N.register(
"%1$s commented on %2$s" : "%1$s коментиран за %2$s",
"{author} commented on {file}" : "{author} коментира за {file}",
"<strong>Comments</strong> for files" : "<strong>Коментари</strong> за файлове",
"You were mentioned on \"{file}\", in a comment by a user that has since been deleted" : "Бяхте споменат/а към “{file}”, в коментар от потребител, който вече е изтрит",
"{user} mentioned you in a comment on \"{file}\"" : "{user} ви спомена в коментар за “{file}”",
"Files app plugin to add comments to files" : "Добавка на приложението Файлове за добавяне на коментари към файловете",
"Edit comment" : "Редактирай коментра",
@ -26,7 +25,7 @@ OC.L10N.register(
"Comment deleted" : " Изтрит е коментар",
"An error occurred while trying to delete the comment" : "Възникна грешка при опит за изтриване на коментара",
"An error occurred while trying to create the comment" : "Възникна грешка при опит за създаване на коментар",
"%1$s commented" : "%1$s коментира",
"You were mentioned on \"{file}\", in a comment by a user that has since been deleted" : "Бяхте споменат/а към “{file}”, в коментар от потребител, който вече е изтрит",
"_%n unread comment_::_%n unread comments_" : ["%n непрочетен коментар","%n непрочетени коментари"]
},
"nplurals=2; plural=(n != 1);");

@ -7,7 +7,6 @@
"%1$s commented on %2$s" : "%1$s коментиран за %2$s",
"{author} commented on {file}" : "{author} коментира за {file}",
"<strong>Comments</strong> for files" : "<strong>Коментари</strong> за файлове",
"You were mentioned on \"{file}\", in a comment by a user that has since been deleted" : "Бяхте споменат/а към “{file}”, в коментар от потребител, който вече е изтрит",
"{user} mentioned you in a comment on \"{file}\"" : "{user} ви спомена в коментар за “{file}”",
"Files app plugin to add comments to files" : "Добавка на приложението Файлове за добавяне на коментари към файловете",
"Edit comment" : "Редактирай коментра",
@ -24,7 +23,7 @@
"Comment deleted" : " Изтрит е коментар",
"An error occurred while trying to delete the comment" : "Възникна грешка при опит за изтриване на коментара",
"An error occurred while trying to create the comment" : "Възникна грешка при опит за създаване на коментар",
"%1$s commented" : "%1$s коментира",
"You were mentioned on \"{file}\", in a comment by a user that has since been deleted" : "Бяхте споменат/а към “{file}”, в коментар от потребител, който вече е изтрит",
"_%n unread comment_::_%n unread comments_" : ["%n непрочетен коментар","%n непрочетени коментари"]
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}

@ -9,13 +9,14 @@ OC.L10N.register(
"%1$s commented on %2$s" : "%1$s ha escrit un comentari a %2$s",
"{author} commented on {file}" : "{author} ha escrit un comentari a {file}",
"<strong>Comments</strong> for files" : "<strong>Comentaris</strong> per a fitxers",
"You were mentioned on \"{file}\", in a comment by a user that has since been deleted" : "Se us ha esmentat a «{file}» en un comentari d'un usuari que s'ha suprimit",
"{user} mentioned you in a comment on \"{file}\"" : "{user} us ha esmentat en un comentari a «{file}»",
"Files app plugin to add comments to files" : "Connector de l'aplicació Fitxers per a afegir comentaris als fitxers",
"Edit comment" : "Edita el comentari",
"Delete comment" : "Suprimeix el comentari",
"Cancel edit" : "Cancel·la l'edició",
"Post comment" : "Publica el comentari",
"@ for mentions, : for emoji, / for smart picker" : "@ per a mencions, : per a emojis, / per al selector intel·ligent",
"Could not reload comments" : "No s'han pogut tornar a carregar els comentaris",
"No comments yet, start the conversation!" : "Encara no hi ha cap comentari. Enceteu la conversa!",
"No more messages" : "No hi ha més missatges",
"Retry" : "Torna-ho a provar",
@ -27,7 +28,7 @@ OC.L10N.register(
"Comment deleted" : "S'ha suprimit el comentari",
"An error occurred while trying to delete the comment" : "S'ha produït un error en intentar suprimir el comentari",
"An error occurred while trying to create the comment" : "S'ha produït un error en intentar crear el comentari",
"%1$s commented" : "%1$s ha escrit un comentari",
"You were mentioned on \"{file}\", in a comment by a user that has since been deleted" : "Se us ha esmentat a «{file}» en un comentari d'un usuari que s'ha suprimit",
"_%n unread comment_::_%n unread comments_" : ["%n comentari sense llegir","%n comentaris sense llegir"]
},
"nplurals=2; plural=(n != 1);");

@ -7,13 +7,14 @@
"%1$s commented on %2$s" : "%1$s ha escrit un comentari a %2$s",
"{author} commented on {file}" : "{author} ha escrit un comentari a {file}",
"<strong>Comments</strong> for files" : "<strong>Comentaris</strong> per a fitxers",
"You were mentioned on \"{file}\", in a comment by a user that has since been deleted" : "Se us ha esmentat a «{file}» en un comentari d'un usuari que s'ha suprimit",
"{user} mentioned you in a comment on \"{file}\"" : "{user} us ha esmentat en un comentari a «{file}»",
"Files app plugin to add comments to files" : "Connector de l'aplicació Fitxers per a afegir comentaris als fitxers",
"Edit comment" : "Edita el comentari",
"Delete comment" : "Suprimeix el comentari",
"Cancel edit" : "Cancel·la l'edició",
"Post comment" : "Publica el comentari",
"@ for mentions, : for emoji, / for smart picker" : "@ per a mencions, : per a emojis, / per al selector intel·ligent",
"Could not reload comments" : "No s'han pogut tornar a carregar els comentaris",
"No comments yet, start the conversation!" : "Encara no hi ha cap comentari. Enceteu la conversa!",
"No more messages" : "No hi ha més missatges",
"Retry" : "Torna-ho a provar",
@ -25,7 +26,7 @@
"Comment deleted" : "S'ha suprimit el comentari",
"An error occurred while trying to delete the comment" : "S'ha produït un error en intentar suprimir el comentari",
"An error occurred while trying to create the comment" : "S'ha produït un error en intentar crear el comentari",
"%1$s commented" : "%1$s ha escrit un comentari",
"You were mentioned on \"{file}\", in a comment by a user that has since been deleted" : "Se us ha esmentat a «{file}» en un comentari d'un usuari que s'ha suprimit",
"_%n unread comment_::_%n unread comments_" : ["%n comentari sense llegir","%n comentaris sense llegir"]
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}

@ -9,14 +9,16 @@ OC.L10N.register(
"%1$s commented on %2$s" : "%1$s okomentoval(a) %2$s",
"{author} commented on {file}" : "{author} okomentoval(a) {file}",
"<strong>Comments</strong> for files" : "<strong>Komentáře</strong> k souborům",
"You were mentioned on \"{file}\", in a comment by a user that has since been deleted" : "Byli jste zmíněni u souboru „{file}“, v komentáři od uživatele, který byl později smazán",
"{user} mentioned you in a comment on \"{file}\"" : "{user} vás zmínil(a) v komentáři u „{file}“",
"Files app plugin to add comments to files" : "Zásuvný modul do aplikace Soubory pro přidávání komentářů k souborům",
"Edit comment" : "Upravit komentář",
"Delete comment" : "Smazat komentář",
"Cancel edit" : "Zrušit úpravu",
"New comment" : "Nový komentář",
"Write a comment …" : "Napsat komentář…",
"Post comment" : "Odeslat komentář",
"\"@\" for mentions, \":\" for emoji, \"/\" for smart picker" : "„@“ pro zmínění, „:“ pro emotikony, „/“ pro inteligentní výběr",
"@ for mentions, : for emoji, / for smart picker" : "@ pro zmínění, : pro emotikony, / pro inteligentní výběr",
"Could not reload comments" : "Znovunačtení komentářů se nezdařilo",
"No comments yet, start the conversation!" : "Zatím bez komentářů, začněte konverzaci!",
"No more messages" : "Žádné další zprávy",
"Retry" : "Zkusit znovu",
@ -28,7 +30,7 @@ OC.L10N.register(
"Comment deleted" : "Komentář smazán",
"An error occurred while trying to delete the comment" : "Došlo k chybě při pokusu o smazání komentáře",
"An error occurred while trying to create the comment" : "Došlo k chybě při pokusu o vytvoření komentáře",
"%1$s commented" : "%1$s okomentováno",
"You were mentioned on \"{file}\", in a comment by a user that has since been deleted" : "Byli jste zmíněni u souboru „{file}“, v komentáři od uživatele, který byl později smazán",
"_%n unread comment_::_%n unread comments_" : ["%n nepřečtený komentář","%n nepřečtené komentáře","%n nepřečtených komentářů","%n nepřečtené komentáře"]
},
"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;");

@ -7,14 +7,16 @@
"%1$s commented on %2$s" : "%1$s okomentoval(a) %2$s",
"{author} commented on {file}" : "{author} okomentoval(a) {file}",
"<strong>Comments</strong> for files" : "<strong>Komentáře</strong> k souborům",
"You were mentioned on \"{file}\", in a comment by a user that has since been deleted" : "Byli jste zmíněni u souboru „{file}“, v komentáři od uživatele, který byl později smazán",
"{user} mentioned you in a comment on \"{file}\"" : "{user} vás zmínil(a) v komentáři u „{file}“",
"Files app plugin to add comments to files" : "Zásuvný modul do aplikace Soubory pro přidávání komentářů k souborům",
"Edit comment" : "Upravit komentář",
"Delete comment" : "Smazat komentář",
"Cancel edit" : "Zrušit úpravu",
"New comment" : "Nový komentář",
"Write a comment …" : "Napsat komentář…",
"Post comment" : "Odeslat komentář",
"\"@\" for mentions, \":\" for emoji, \"/\" for smart picker" : "„@“ pro zmínění, „:“ pro emotikony, „/“ pro inteligentní výběr",
"@ for mentions, : for emoji, / for smart picker" : "@ pro zmínění, : pro emotikony, / pro inteligentní výběr",
"Could not reload comments" : "Znovunačtení komentářů se nezdařilo",
"No comments yet, start the conversation!" : "Zatím bez komentářů, začněte konverzaci!",
"No more messages" : "Žádné další zprávy",
"Retry" : "Zkusit znovu",
@ -26,7 +28,7 @@
"Comment deleted" : "Komentář smazán",
"An error occurred while trying to delete the comment" : "Došlo k chybě při pokusu o smazání komentáře",
"An error occurred while trying to create the comment" : "Došlo k chybě při pokusu o vytvoření komentáře",
"%1$s commented" : "%1$s okomentováno",
"You were mentioned on \"{file}\", in a comment by a user that has since been deleted" : "Byli jste zmíněni u souboru „{file}“, v komentáři od uživatele, který byl později smazán",
"_%n unread comment_::_%n unread comments_" : ["%n nepřečtený komentář","%n nepřečtené komentáře","%n nepřečtených komentářů","%n nepřečtené komentáře"]
},"pluralForm" :"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;"
}

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

Loading…
Cancel
Save