From a77040f41edb037a3d5955a05e0d31e4b1664550 Mon Sep 17 00:00:00 2001 From: Anna Larch Date: Thu, 12 Mar 2026 19:23:23 +0100 Subject: [PATCH] chore(workflows): remove cypress cloud and allow regular cypress tests to run on forks (no secret leaked) add consistent gating for changes remove empty matrix option skip performance workflow on forks without it looking like it's failing Signed-off-by: Anna Larch --- .github/workflows/autocheckers.yml | 5 +- .github/workflows/command-pull-3rdparty.yml | 49 +++++--- .github/workflows/cypress.yml | 11 -- .github/workflows/files-external-sftp.yml | 2 +- .github/workflows/integration-dav.yml | 112 +++++++++--------- .github/workflows/integration-s3-primary.yml | 1 - .github/workflows/lint-php-cs.yml | 3 + .github/workflows/lint-stylelint.yml | 43 +++++++ .github/workflows/node-test.yml | 3 - .github/workflows/object-storage-s3.yml | 1 - .github/workflows/performance.yml | 13 +- .../phpunit-object-store-primary.yml | 2 +- .../update-min-supported-desktop.yml | 2 +- 13 files changed, 146 insertions(+), 101 deletions(-) diff --git a/.github/workflows/autocheckers.yml b/.github/workflows/autocheckers.yml index 375ecf0d7dd..6ebd87f3b6f 100644 --- a/.github/workflows/autocheckers.yml +++ b/.github/workflows/autocheckers.yml @@ -74,6 +74,9 @@ jobs: autocheckers: runs-on: ubuntu-latest-low + needs: changes + if: needs.changes.outputs.src != 'false' + strategy: matrix: php-versions: ['8.2'] @@ -125,4 +128,4 @@ jobs: steps: - name: Summary status - run: if ${{ needs.autocheckers.result != 'success' || (needs.changes.outputs.src != 'false' && needs.autoloader.result != 'success') }}; then exit 1; fi + run: if ${{ needs.changes.outputs.src != 'false' && (needs.autocheckers.result != 'success' || needs.autoloader.result != 'success') }}; then exit 1; fi diff --git a/.github/workflows/command-pull-3rdparty.yml b/.github/workflows/command-pull-3rdparty.yml index 8a0e7fbc865..97ea974ea1a 100644 --- a/.github/workflows/command-pull-3rdparty.yml +++ b/.github/workflows/command-pull-3rdparty.yml @@ -14,6 +14,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: none + pull-requests: read # On pull requests and if the comment starts with `/update-3rdparty` if: github.event.issue.pull_request != '' && startsWith(github.event.comment.body, '/update-3rdparty') @@ -27,8 +28,25 @@ jobs: comment-id: ${{ github.event.comment.id }} reactions: '+1' + # issue_comment events carry no pull_request context in their payload, so we + # must fetch the PR via the API. This also gives us base.ref for free, avoiding + # a second API call. The GITHUB_TOKEN needs pull-requests:read (granted above). + - name: Get pull request metadata + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + id: get-pr + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const pull = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.issue.number, + }); + core.setOutput('head_repo', pull.data.head.repo?.full_name ?? ''); + core.setOutput('base_ref', pull.data.base.ref); + - name: Disabled on forks - if: ${{ github.event.pull_request.head.repo.full_name != github.repository }} + if: steps.get-pr.outputs.head_repo != github.repository run: | echo 'Can not execute /update-3rdparty on forks' exit 1 @@ -46,24 +64,17 @@ jobs: ref: ${{ steps.comment-branch.outputs.head_ref }} - name: Register server reference to fallback to master branch - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - github-token: ${{secrets.GITHUB_TOKEN}} - script: | - const baseRef = context.payload.pull_request.base.ref - if (baseRef === 'main' || baseRef === 'master') { - core.exportVariable('server_ref', 'master'); - console.log('Setting server_ref to master'); - } else { - const regex = /^stable(\d+)$/ - const match = baseRef.match(regex) - if (match) { - core.exportVariable('server_ref', match[0]); - console.log('Setting server_ref to ' + match[0]); - } else { - console.log('Not based on master/main/stable*, so skipping pull 3rdparty command'); - } - } + run: | + base_ref="${{ steps.get-pr.outputs.base_ref }}" + if [[ "$base_ref" == "main" || "$base_ref" == "master" ]]; then + echo "server_ref=master" >> "$GITHUB_ENV" + echo "Setting server_ref to master" + elif [[ "$base_ref" =~ ^stable[0-9]+$ ]]; then + echo "server_ref=$base_ref" >> "$GITHUB_ENV" + echo "Setting server_ref to $base_ref" + else + echo "Not based on master/main/stable*, so skipping pull 3rdparty command" + fi - name: Setup git run: | diff --git a/.github/workflows/cypress.yml b/.github/workflows/cypress.yml index dc1730f35a4..d62a121760c 100644 --- a/.github/workflows/cypress.yml +++ b/.github/workflows/cypress.yml @@ -41,12 +41,6 @@ jobs: PUPPETEER_SKIP_DOWNLOAD: true steps: - - name: Disabled on forks - if: ${{ github.event.pull_request.head.repo.full_name != github.repository }} - run: | - echo 'Can not run cypress on forks' - exit 1 - - name: Checkout server uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: @@ -176,10 +170,6 @@ jobs: # We already installed the dependencies in the init job install: false component: ${{ matrix.containers == 'component' }} - group: ${{ matrix.use-cypress-cloud && matrix.containers == 'component' && 'Run component' || matrix.use-cypress-cloud && 'Run E2E' || '' }} - # cypress env - ci-build-id: ${{ matrix.use-cypress-cloud && format('{0}-{1}', github.sha, github.run_number) || '' }} - tag: ${{ matrix.use-cypress-cloud && github.event_name || '' }} env: # Needs to be prefixed with CYPRESS_ CYPRESS_BRANCH: ${{ env.BRANCH }} @@ -188,7 +178,6 @@ jobs: # Needed for some specific code workarounds TESTING: true GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} SPLIT: ${{ matrix.total-containers }} SPLIT_INDEX: ${{ matrix.containers == 'component' && 0 || matrix.containers }} SPLIT_RANDOM_SEED: ${{ github.run_id }} diff --git a/.github/workflows/files-external-sftp.yml b/.github/workflows/files-external-sftp.yml index 9e86a08bfd7..97b5873ff4f 100644 --- a/.github/workflows/files-external-sftp.yml +++ b/.github/workflows/files-external-sftp.yml @@ -73,7 +73,7 @@ jobs: - name: Set up sftpd run: | sudo mkdir /tmp/sftp - sudo chown -R 0777 /tmp/sftp + sudo chmod -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 }} diff --git a/.github/workflows/integration-dav.yml b/.github/workflows/integration-dav.yml index 4939d120487..05bacd8cef4 100644 --- a/.github/workflows/integration-dav.yml +++ b/.github/workflows/integration-dav.yml @@ -52,69 +52,69 @@ jobs: name: ${{ matrix.service }} (${{ matrix.endpoint }} endpoint) php${{ matrix.php-versions }} steps: - - name: Checkout server - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - submodules: true + - name: Checkout server + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + submodules: true - - name: Set up php ${{ matrix.php-versions }} - uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 #v2.36.0 - timeout-minutes: 5 - with: - php-version: ${{ matrix.php-versions }} - # https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation - extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, redis, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite - coverage: 'none' - ini-file: development - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Set up php ${{ matrix.php-versions }} + uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 #v2.36.0 + timeout-minutes: 5 + with: + php-version: ${{ matrix.php-versions }} + # https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation + extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, redis, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite + coverage: 'none' + ini-file: development + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Set up Python - uses: LizardByte/actions/actions/setup_python@70bb8d394d1c92f6113aeec6ae9cc959a5763d15 # v2026.227.200013 - with: - python-version: '2.7' + - name: Set up Python + uses: LizardByte/actions/actions/setup_python@70bb8d394d1c92f6113aeec6ae9cc959a5763d15 # v2026.227.200013 + with: + python-version: '2.7' - - name: Set up CalDAVTester - run: | - git clone --depth=1 https://github.com/apple/ccs-caldavtester.git CalDAVTester - git clone --depth=1 https://github.com/apple/ccs-pycalendar.git pycalendar + - name: Set up CalDAVTester + run: | + git clone --depth=1 https://github.com/apple/ccs-caldavtester.git CalDAVTester + git clone --depth=1 https://github.com/apple/ccs-pycalendar.git pycalendar - - name: Set up Nextcloud - run: | - mkdir data - ./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-host=127.0.0.1 --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin - # disable the trashbin, so recurrent deletion of the same object works - ./occ config:app:set dav calendarRetentionObligation --value=0 - # Prepare users - OC_PASS=user01 ./occ user:add --password-from-env user01 - OC_PASS=user02 ./occ user:add --password-from-env user02 - # Prepare calendars - ./occ dav:create-calendar user01 calendar - ./occ dav:create-calendar user01 shared - ./occ dav:create-calendar user02 calendar - # Prepare address books - ./occ dav:create-addressbook user01 addressbook - ./occ dav:create-addressbook user02 addressbook + - name: Set up Nextcloud + run: | + mkdir data + ./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-host=127.0.0.1 --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin + # disable the trashbin, so recurrent deletion of the same object works + ./occ config:app:set dav calendarRetentionObligation --value=0 + # Prepare users + OC_PASS=user01 ./occ user:add --password-from-env user01 + OC_PASS=user02 ./occ user:add --password-from-env user02 + # Prepare calendars + ./occ dav:create-calendar user01 calendar + ./occ dav:create-calendar user01 shared + ./occ dav:create-calendar user02 calendar + # Prepare address books + ./occ dav:create-addressbook user01 addressbook + ./occ dav:create-addressbook user02 addressbook - - name: Run Nextcloud - run: | - php -S localhost:8888 & + - name: Run Nextcloud + run: | + php -S localhost:8888 & - - name: Run CalDAVTester - run: | - cp "apps/dav/tests/testsuits/caldavtest/serverinfo-${{ matrix.endpoint }}${{ matrix.endpoint == 'old' && (matrix.service == 'CardDAV' && '-carddav' || '-caldav') || '' }}-endpoint.xml" "apps/dav/tests/testsuits/caldavtest/serverinfo.xml" - pushd CalDAVTester - PYTHONPATH="../pycalendar/src" python testcaldav.py --print-details-onfail --basedir "../apps/dav/tests/testsuits/caldavtest" -o cdt.txt \ - "${{ matrix.service }}/current-user-principal.xml" \ - "${{ matrix.service }}/sync-report.xml" \ - ${{ matrix.endpoint == 'new' && format('{0}/sharing-{1}.xml', matrix.service, matrix.service == 'CalDAV' && 'calendars' || 'addressbooks') || ';' }} - popd + - name: Run CalDAVTester + run: | + cp "apps/dav/tests/testsuits/caldavtest/serverinfo-${{ matrix.endpoint }}${{ matrix.endpoint == 'old' && (matrix.service == 'CardDAV' && '-carddav' || '-caldav') || '' }}-endpoint.xml" "apps/dav/tests/testsuits/caldavtest/serverinfo.xml" + pushd CalDAVTester + PYTHONPATH="../pycalendar/src" python testcaldav.py --print-details-onfail --basedir "../apps/dav/tests/testsuits/caldavtest" -o cdt.txt \ + "${{ matrix.service }}/current-user-principal.xml" \ + "${{ matrix.service }}/sync-report.xml" \ + ${{ matrix.endpoint == 'new' && format('{0}/sharing-{1}.xml', matrix.service, matrix.service == 'CalDAV' && 'calendars' || 'addressbooks') || ';' }} + popd - - name: Print Nextcloud logs - if: always() - run: | - cat data/nextcloud.log + - name: Print Nextcloud logs + if: always() + run: | + cat data/nextcloud.log caldav-integration-summary: permissions: diff --git a/.github/workflows/integration-s3-primary.yml b/.github/workflows/integration-s3-primary.yml index 7fe880c4889..dac758be560 100644 --- a/.github/workflows/integration-s3-primary.yml +++ b/.github/workflows/integration-s3-primary.yml @@ -95,7 +95,6 @@ jobs: - 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 diff --git a/.github/workflows/lint-php-cs.yml b/.github/workflows/lint-php-cs.yml index c5817919967..a3b8ed86b11 100644 --- a/.github/workflows/lint-php-cs.yml +++ b/.github/workflows/lint-php-cs.yml @@ -44,6 +44,9 @@ jobs: lint: runs-on: ubuntu-latest + needs: changes + if: needs.changes.outputs.src != 'false' + name: php-cs steps: diff --git a/.github/workflows/lint-stylelint.yml b/.github/workflows/lint-stylelint.yml index ce4d6d74d1d..1beeba03d7e 100644 --- a/.github/workflows/lint-stylelint.yml +++ b/.github/workflows/lint-stylelint.yml @@ -18,9 +18,37 @@ concurrency: cancel-in-progress: true jobs: + changes: + runs-on: ubuntu-latest-low + permissions: + contents: read + pull-requests: read + + outputs: + src: ${{ steps.changes.outputs.src }} + + steps: + - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + id: changes + continue-on-error: true + with: + filters: | + src: + - '.github/workflows/**' + - '**/src/**' + - '**/appinfo/info.xml' + - 'package.json' + - 'package-lock.json' + - '**.css' + - '**.scss' + - '**.vue' + lint: runs-on: ubuntu-latest + needs: changes + if: needs.changes.outputs.src != 'false' + name: stylelint steps: @@ -51,3 +79,18 @@ jobs: - name: Lint run: npm run stylelint + + summary: + permissions: + contents: none + runs-on: ubuntu-latest-low + needs: [changes, lint] + + if: always() + + # This is the summary, we just avoid to rename it so that branch protection rules still match + name: stylelint + + steps: + - name: Summary status + run: if ${{ needs.changes.outputs.src != 'false' && needs.lint.result != 'success' }}; then exit 1; fi diff --git a/.github/workflows/node-test.yml b/.github/workflows/node-test.yml index bba874c2cf6..c8f2ce840cb 100644 --- a/.github/workflows/node-test.yml +++ b/.github/workflows/node-test.yml @@ -83,9 +83,6 @@ jobs: run: | npm ci -# - name: Test -# run: npm run test --if-present - - name: Test and process coverage run: npm run test:coverage diff --git a/.github/workflows/object-storage-s3.yml b/.github/workflows/object-storage-s3.yml index 8fb63b00207..6cfd0e0a552 100644 --- a/.github/workflows/object-storage-s3.yml +++ b/.github/workflows/object-storage-s3.yml @@ -111,7 +111,6 @@ jobs: - 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 diff --git a/.github/workflows/performance.yml b/.github/workflows/performance.yml index abcc463f5d8..6d23e493712 100644 --- a/.github/workflows/performance.yml +++ b/.github/workflows/performance.yml @@ -15,7 +15,13 @@ jobs: performance-testing: runs-on: ubuntu-latest - if: ${{ github.repository_owner != 'nextcloud-gmbh' }} + # Skip entirely on fork PRs so the job result is 'skipped' rather than + # 'failure'. The profiler action uses github.event.pull_request.head.repo.clone_url + # and GITHUB_TOKEN in ways that do not work reliably from forks, and a + # clean skip is far less confusing for contributors than a mid-run error. + if: >- + github.repository_owner != 'nextcloud-gmbh' && + github.event.pull_request.head.repo.full_name == github.repository permissions: pull-requests: write @@ -28,11 +34,6 @@ jobs: name: performance-${{ matrix.php-versions }} steps: - - name: Disabled on forks - if: ${{ github.event.pull_request.head.repo.full_name != github.repository }} - run: | - echo 'Can not run performance tests on forks' - exit 1 - name: Checkout server before PR uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 diff --git a/.github/workflows/phpunit-object-store-primary.yml b/.github/workflows/phpunit-object-store-primary.yml index 0ea1fbcfba6..cffce0dd8ff 100644 --- a/.github/workflows/phpunit-object-store-primary.yml +++ b/.github/workflows/phpunit-object-store-primary.yml @@ -104,7 +104,7 @@ jobs: curl -f -m 1 --retry-connrefused --retry 10 --retry-delay 10 http://localhost:9000/minio/health/ready - name: PHPUnit - run: composer run test:db + run: composer run test:db -- --log-junit junit.xml - name: S3 logs if: always() diff --git a/.github/workflows/update-min-supported-desktop.yml b/.github/workflows/update-min-supported-desktop.yml index dd65b1af60e..3413147a649 100644 --- a/.github/workflows/update-min-supported-desktop.yml +++ b/.github/workflows/update-min-supported-desktop.yml @@ -115,7 +115,7 @@ jobs: committer: GitHub author: nextcloud-command signoff: true - branch: "automated/noid/${{ matrix.branches }}-update-min-supported-desktop-version" + branch: "automated/noid/update-min-supported-desktop-version" title: "chore: Update minimum supported desktop version to ${{ steps.extract-version.outputs.VERSION }}" base: "master" body: |