Continuous Integration

We highly recommend setting up automated tests for your app, so that every change has to pass a defined procedure before it’s accepted into the main branch of your repository. Continuous integration typically includes

  • Linting: check the syntax of source files, e.g. of all php scripts
  • Static analysis: have tools check the types in your app for type soundness, mostly used for php
  • Unit testing: run unit tests for front-end and back-end where individual classes and components are tested in isolation
  • Integration testing: test components when they are combined

Linting

info.xml

You can validate the info.xml app metadata file of an app with a simple github action:

  1. name: Lint
  2. on: pull_request
  3. jobs:
  4. xml-linters:
  5. runs-on: ubuntu-latest
  6. steps:
  7. - name: Checkout
  8. uses: actions/checkout@master
  9. - name: Download schema
  10. run: wget https://apps.nextcloud.com/schema/apps/info.xsd
  11. - name: Lint info.xml
  12. uses: ChristophWurst/xmllint-action@v1
  13. with:
  14. xml-file: ./appinfo/info.xml
  15. xml-schema-file: ./info.xsd

php

A lint of all php source files can find syntax errors that could crash the application in production. The github action below uses a test matrix of multiple php versions. Adjust it to the ones your app supports.

  1. name: Lint
  2. on: pull_request
  3. php-linters:
  4. runs-on: ubuntu-latest
  5. strategy:
  6. matrix:
  7. php-versions: [7.3, 7.4]
  8. name: php${{ matrix.php-versions }} lint
  9. steps:
  10. - name: Checkout
  11. uses: actions/checkout@master
  12. - name: Set up php${{ matrix.php-versions }}
  13. uses: shivammathur/setup-php@master
  14. with:
  15. php-version: ${{ matrix.php-versions }}
  16. coverage: none
  17. - name: Lint
  18. run: composer run lint

Static analysis

Psalm is a static analysis tool that can check if your app code uses all types correctly, like if classes and methods exist. For the basic setup see the Psalm website. In order to let Psalm know about Nextcloud interfaces (the OCP namespace), you can install the API package. Afterwards you’ll be able to check the app with the following psalm.xml that should be put into the root of the app.

  1. <?xml version="1.0"?>
  2. <psalm
  3. totallyTyped="true"
  4. errorLevel="5"
  5. resolveFromConfigFile="true"
  6. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  7. xmlns="https://getpsalm.org/schema/config"
  8. xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
  9. errorBaseline="tests/psalm-baseline.xml"
  10. >
  11. <projectFiles>
  12. <directory name="lib" />
  13. <ignoreFiles>
  14. <directory name="vendor" />
  15. <directory name="lib/Vendor" />
  16. </ignoreFiles>
  17. </projectFiles>
  18. <extraFiles>
  19. <directory name="vendor" />
  20. <ignoreFiles>
  21. <directory name="vendor/phpunit/php-code-coverage" />
  22. </ignoreFiles>
  23. </extraFiles>
  24. <issueHandlers>
  25. <UndefinedClass>
  26. <errorLevel type="suppress">
  27. <referencedClass name="OC" />
  28. </errorLevel>
  29. </UndefinedClass>
  30. <UndefinedDocblockClass>
  31. <errorLevel type="suppress">
  32. <referencedClass name="Doctrine\DBAL\Schema\Schema" />
  33. <referencedClass name="Doctrine\DBAL\Schema\SchemaException" />
  34. <referencedClass name="Doctrine\DBAL\Driver\Statement" />
  35. <referencedClass name="Doctrine\DBAL\Schema\Table" />
  36. </errorLevel>
  37. </UndefinedDocblockClass>
  38. </issueHandlers>
  39. </psalm>

Note

The definition supresses usages of the global and static class OC like \OC::$server, which is discouraged but still found in some apps. The doctrine supression is currently necessary as the database mappers and schema abstractions leak some of the 3rd party libraries of Nextcloud that are not known to Psalm.

You can put this process into a Github Action that is run for every pull request.

  1. name: Static analysis
  2. on: [push]
  3. jobs:
  4. static-psalm-analysis:
  5. runs-on: ubuntu-latest
  6. strategy:
  7. matrix:
  8. ocp-version: [ 'dev-master', 'v20.0.0' ]
  9. name: Nextcloud ${{ matrix.ocp-version }}
  10. steps:
  11. - name: Checkout
  12. uses: actions/checkout@master
  13. - name: Set up php
  14. uses: shivammathur/setup-php@master
  15. with:
  16. php-version: 7.4
  17. coverage: none
  18. - name: Install dependencies
  19. run: composer i
  20. - name: Install dependencies
  21. run: composer require --dev christophwurst/nextcloud:${{ matrix.ocp-version }}
  22. - name: Run coding standards check
  23. run: composer run psalm

This creates a matrix, where the app is tested against dev-master, the latest version of OCP found in the main branch of Nextcloud server, as well as v20.0.0, the currently latest stable release. Adjust this to your needs.