diff --git a/.github/actions/matrix/matrix_includes.yml b/.github/actions/matrix/matrix_includes.yml index b32f0e0..38d86b4 100644 --- a/.github/actions/matrix/matrix_includes.yml +++ b/.github/actions/matrix/matrix_includes.yml @@ -1,28 +1,23 @@ include: # Always include main (issue #18) - disable-able by config by setting 'disable_master' to true - - {moodle-branch: 'main', php: '8.4', node: '22.11', mariadb-ver: '10.11', pgsql-ver: '14', database: 'pgsql'} + - {moodle-branch: 'main', php: '8.4', node: '22', mariadb-ver: '10.11', pgsql-ver: '15', database: 'pgsql'} # Test all variants of 5.1 - - { moodle-branch: 'MOODLE_501_STABLE', php: '8.4', node: '22.11', mariadb-ver: '10.11', pgsql-ver: '15', database: 'mariadb' } - - { moodle-branch: 'MOODLE_501_STABLE', php: '8.4', node: '22.11', mariadb-ver: '10.11', pgsql-ver: '15', database: 'pgsql' } - - { moodle-branch: 'MOODLE_501_STABLE', php: '8.2', node: '22.11', mariadb-ver: '10.11', pgsql-ver: '15', database: 'mariadb' } - - { moodle-branch: 'MOODLE_501_STABLE', php: '8.2', node: '22.11', mariadb-ver: '10.11', pgsql-ver: '15', database: 'pgsql' } + - { moodle-branch: 'MOODLE_501_STABLE', php: '8.4', node: '22', mariadb-ver: '10.11', pgsql-ver: '15', database: 'mariadb' } + - { moodle-branch: 'MOODLE_501_STABLE', php: '8.4', node: '22', mariadb-ver: '10.11', pgsql-ver: '15', database: 'pgsql' } + - { moodle-branch: 'MOODLE_501_STABLE', php: '8.2', node: '22', mariadb-ver: '10.11', pgsql-ver: '15', database: 'mariadb' } + - { moodle-branch: 'MOODLE_501_STABLE', php: '8.2', node: '22', mariadb-ver: '10.11', pgsql-ver: '15', database: 'pgsql' } # Test all variants of 5.0 - - { moodle-branch: 'MOODLE_500_STABLE', php: '8.4', node: '22.11', mariadb-ver: '10.11', pgsql-ver: '14', database: 'mariadb' } - - { moodle-branch: 'MOODLE_500_STABLE', php: '8.4', node: '22.11', mariadb-ver: '10.11', pgsql-ver: '14', database: 'pgsql' } - - { moodle-branch: 'MOODLE_500_STABLE', php: '8.2', node: '22.11', mariadb-ver: '10.11', pgsql-ver: '14', database: 'mariadb' } - - { moodle-branch: 'MOODLE_500_STABLE', php: '8.2', node: '22.11', mariadb-ver: '10.11', pgsql-ver: '14', database: 'pgsql' } + - { moodle-branch: 'MOODLE_500_STABLE', php: '8.4', node: '22', mariadb-ver: '10.11', pgsql-ver: '14', database: 'mariadb' } + - { moodle-branch: 'MOODLE_500_STABLE', php: '8.4', node: '22', mariadb-ver: '10.11', pgsql-ver: '14', database: 'pgsql' } + - { moodle-branch: 'MOODLE_500_STABLE', php: '8.2', node: '22', mariadb-ver: '10.11', pgsql-ver: '14', database: 'mariadb' } + - { moodle-branch: 'MOODLE_500_STABLE', php: '8.2', node: '22', mariadb-ver: '10.11', pgsql-ver: '14', database: 'pgsql' } # Test all variants of 4.5. - - { moodle-branch: 'MOODLE_405_STABLE', php: '8.3', node: '20.11', mariadb-ver: '10.6', pgsql-ver: '13', database: 'mariadb' } - - { moodle-branch: 'MOODLE_405_STABLE', php: '8.3', node: '20.11', mariadb-ver: '10.6', pgsql-ver: '13', database: 'pgsql' } - - { moodle-branch: 'MOODLE_405_STABLE', php: '8.1', node: '20.11', mariadb-ver: '10.6', pgsql-ver: '13', database: 'mariadb' } - - { moodle-branch: 'MOODLE_405_STABLE', php: '8.1', node: '20.11', mariadb-ver: '10.6', pgsql-ver: '13', database: 'pgsql' } + - { moodle-branch: 'MOODLE_405_STABLE', php: '8.3', node: '22', mariadb-ver: '10.6', pgsql-ver: '13', database: 'mariadb' } + - { moodle-branch: 'MOODLE_405_STABLE', php: '8.3', node: '22', mariadb-ver: '10.6', pgsql-ver: '13', database: 'pgsql' } + - { moodle-branch: 'MOODLE_405_STABLE', php: '8.1', node: '22', mariadb-ver: '10.6', pgsql-ver: '13', database: 'mariadb' } + - { moodle-branch: 'MOODLE_405_STABLE', php: '8.1', node: '22', mariadb-ver: '10.6', pgsql-ver: '13', database: 'pgsql' } # Test all variants of 4.1 (LTS). - - { moodle-branch: 'MOODLE_401_STABLE', php: '7.4', node: '20.11', mariadb-ver: '10.5', pgsql-ver: '12', database: 'mariadb' } - - { moodle-branch: 'MOODLE_401_STABLE', php: '7.4', node: '20.11', mariadb-ver: '10.5', pgsql-ver: '12', database: 'pgsql' } - - { moodle-branch: 'MOODLE_401_STABLE', php: '8.0', node: '20.11', mariadb-ver: '10.5', pgsql-ver: '12', database: 'mariadb' } - - { moodle-branch: 'MOODLE_401_STABLE', php: '8.0', node: '20.11', mariadb-ver: '10.5', pgsql-ver: '12', database: 'pgsql' } - # Also test all variants of 3.9 (LTS). - - {moodle-branch: 'MOODLE_39_STABLE', php: '7.4', node: '16.20', mariadb-ver: '10.5', pgsql-ver: '10', database: 'mariadb'} - - {moodle-branch: 'MOODLE_39_STABLE', php: '7.4', node: '16.20', mariadb-ver: '10.5', pgsql-ver: '10', database: 'pgsql'} - - {moodle-branch: 'MOODLE_39_STABLE', php: '7.4', node: '16.20', mariadb-ver: '10.5', pgsql-ver: '10', database: 'mariadb'} - - {moodle-branch: 'MOODLE_39_STABLE', php: '7.4', node: '16.20', mariadb-ver: '10.5', pgsql-ver: '10', database: 'pgsql'} + - { moodle-branch: 'MOODLE_401_STABLE', php: '7.4', node: '22', mariadb-ver: '10.5', pgsql-ver: '12', database: 'mariadb' } + - { moodle-branch: 'MOODLE_401_STABLE', php: '7.4', node: '22', mariadb-ver: '10.5', pgsql-ver: '12', database: 'pgsql' } + - { moodle-branch: 'MOODLE_401_STABLE', php: '8.0', node: '22', mariadb-ver: '10.5', pgsql-ver: '12', database: 'mariadb' } + - { moodle-branch: 'MOODLE_401_STABLE', php: '8.0', node: '22', mariadb-ver: '10.5', pgsql-ver: '12', database: 'pgsql' } diff --git a/.github/actions/parse-version/script.php b/.github/actions/parse-version/script.php index ced1688..37d39dd 100644 --- a/.github/actions/parse-version/script.php +++ b/.github/actions/parse-version/script.php @@ -63,6 +63,16 @@ function output(string $name, string $value) { $updates = json_decode(file_get_contents('https://download.moodle.org/api/1.3/updates.php?format=json&version=0.0&branch=3.8'), true); $updates = $updates['updates']['core'] ?? []; + +// Helper to normalize container name +function container_image_name($moodle_branch, $php) { + $repo = 'catalyst-moodle-workflows-' + . str_replace('_', '-', strtolower($moodle_branch)) + . '-' + . str_replace('_', '-', strtolower($php)); + return "ghcr.io/catalyst/$repo:latest"; +} + $preparedMatrix = array_filter($matrix['include'], function($entry) use($plugin, $updates, $matrix) { if (!isset($entry)) { @@ -161,12 +171,49 @@ function output(string $name, string $value) { return false; }); -$jsonMatrix = json_encode(['include' => array_values($preparedMatrix)], JSON_UNESCAPED_SLASHES); + +// Add container image name to each entry +$finalMatrix = array_map(function($entry) { + $entry['container'] = container_image_name($entry['moodle-branch'], $entry['php']); + return $entry; +}, array_values($preparedMatrix)); + +$jsonMatrix = json_encode(['include' => $finalMatrix], JSON_UNESCAPED_SLASHES); output('matrix', $jsonMatrix); // Output the component / plugin name (which would be useful e.g. for a release) output('component', $plugin->component); + // Output the highest available moodle branch in this set, which will be used to // determine whether or not various tests/tasks will run, such as grunt. -output('highest_moodle_branch', reset($preparedMatrix)['moodle-branch'] ?? ''); +$highestMoodleBranch = reset($preparedMatrix)['moodle-branch'] ?? ''; +output('highest_moodle_branch', $highestMoodleBranch); + +// Find the highest PHP version for the highest moodle branch +$phpVersions = []; +foreach ($finalMatrix as $entry) { + if ($entry['moodle-branch'] === $highestMoodleBranch) { + $phpVersions[] = $entry['php']; + } +} +if (!empty($phpVersions)) { + // Use version_compare to find the highest PHP version + usort($phpVersions, 'version_compare'); + $highestPhp = end($phpVersions); + // Find the container for this combo + foreach ($finalMatrix as $entry) { + if ($entry['moodle-branch'] === $highestMoodleBranch && $entry['php'] === $highestPhp) { + output('latest_container', $entry['container']); + if (isset($entry['pgsql-ver'])) { + output('latest_pgsql_ver', $entry['pgsql-ver']); + } else { + output('latest_pgsql_ver', ''); + } + break; + } + } +} else { + output('latest_container', ''); + output('latest_pgsql_ver', ''); +} diff --git a/.github/plugin/setup/action.yml b/.github/plugin/setup/action.yml index b26ffb5..6e0d63e 100644 --- a/.github/plugin/setup/action.yml +++ b/.github/plugin/setup/action.yml @@ -1,36 +1,12 @@ name: 'Plugin setup' description: 'Run plugin setup' inputs: - codechecker_max_warnings: - description: 'Sets the value for --max-warnings on the moodle-plugin-ci codechecker step. Defaults to -1 which means no limit.' - default: '-1' extra_php_extensions: description: 'List of additional php packages to install' extra_plugin_runners: description: 'Command to install dependencies' - disable_behat: - description: 'Option to disable behat tests' - disable_mustache: - description: 'Option to disable mustache tests' - disable_phpdoc: - description: 'Option to disable phpdoc tests' - disable_phpcs: - description: 'Option to disable code standards (codechecker) tests' - disable_phplint: - description: 'Option to disable phplint tests' - disable_phpunit: - description: 'Option to disable phpunit tests' - disable_grunt: - description: 'Option to disable grunt' - enable_phpmd: - description: 'Option to enable phpmd' - disable_phpcpd: - description: 'Option to disable phpcpd' - disable_ci_validate: - description: 'Option to disable running moodle-plugin-ci validate' - - highest_moodle_branch: - description: 'Holds the value of the highest moodle-branch in the test matrix' + moodle_branch: + description: 'Moodle branch to use (for patching)' runs: using: "composite" steps: @@ -39,186 +15,20 @@ runs: with: path: plugin submodules: true - - name: Install node ${{ matrix.node }} - uses: actions/setup-node@v2 - with: - node-version: ${{ matrix.node }} - - - name: Setup PHP ${{ matrix.php }} - uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2.32.0 - with: - php-version: ${{ matrix.php }} - ini-values: max_input_vars=5000 - extensions: pgsql, mysqli, zip, gd, xmlrpc, soap, ${{ inputs.extra_php_extensions }} - coverage: none - - - name: Configure Required Composer Version - id: install-composer1 - if: ${{ matrix.moodle-branch == 'MOODLE_32_STABLE' || matrix.moodle-branch == 'MOODLE_33_STABLE' }} - run: | - echo "::set-output name=COMPOSER_VERSION::--1" - shell: bash - - - name: Update Composer - if: ${{ matrix.moodle-branch == 'MOODLE_32_STABLE' || matrix.moodle-branch == 'MOODLE_33_STABLE' }} - run: | - composer self-update ${{ steps.install-composer1.outputs.COMPOSER_VERSION }} - shell: bash - - - name: Initialise moodle-plugin-ci - run: | - # Initialise moodle-plugin-ci (install via composer) - echo "::group::Initialise moodle-plugin-ci" - - composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci m-ci ^4 - # Add dirs to $PATH - echo $(cd m-ci/bin; pwd) >> $GITHUB_PATH - echo $(cd m-ci/vendor/bin; pwd) >> $GITHUB_PATH - # PHPUnit depends on en_AU.UTF-8 locale - sudo locale-gen en_AU.UTF-8 - - echo "::endgroup::" - shell: bash - - name: Install dependencies if: ${{ inputs.extra_plugin_runners }} run: | # Install dependencies echo "::group::Install dependencies" - ${{ inputs.extra_plugin_runners }} - echo "::endgroup::" shell: bash - - - name: Clone Moodle - # Clone to a temporary directory - run: | - echo "::group::Moodle clone output" - - git clone https://github.com/moodle/moodle.git --branch $MOODLE_BRANCH $GITHUB_WORKSPACE/moodletemp - - echo "::endgroup::" - shell: bash - env: - DB: ${{ matrix.database }} - MOODLE_BRANCH: ${{ matrix.moodle-branch }} - - name: Install Core Patches if: ${{ always() }} - # Install core patches to moodle in temporary directory run: | git config --global user.email "test@test.com" git config --global user.name "Test" - ((test -f plugin/patch/${{ matrix.moodle-branch }}.diff && cd $GITHUB_WORKSPACE/moodletemp && git am --whitespace=nowarn < ../plugin/patch/${{ matrix.moodle-branch }}.diff) || echo No patch found;) - shell: bash - - - name: Install Moodle and Plugin - # Install moodle, but use our temporary directory to include any potential core patches that have been applied. - run: | - # Install moodle commands - echo "::group::Moodle install output" - - # This is a workaround for https://github.com/moodlehq/moodle-plugin-ci/issues/306 - we disable the git repository validation to allow folder cloning. - sed -i '/public function gitUrl($url)/{n; s/{/& return $url;/}' $GITHUB_WORKSPACE/m-ci/src/Validate.php - - moodle-plugin-ci install -vvv --plugin ./plugin --db-host=127.0.0.1 --repo $GITHUB_WORKSPACE/moodletemp - - echo "::endgroup::" - shell: bash - env: - DB: ${{ matrix.database }} - MOODLE_BRANCH: ${{ matrix.moodle-branch }} - - - name: Run phplint - if: ${{ always() && inputs.disable_phplint != 'true' }} - run: moodle-plugin-ci phplint - shell: bash - - - name: Run codechecker - if: ${{ always() && inputs.disable_phpcs != 'true' }} - run: moodle-plugin-ci codechecker --max-warnings=${{ inputs.codechecker_max_warnings }} - shell: bash - - - name: Run validate - if: ${{ always() && inputs.disable_ci_validate != 'true' }} - run: moodle-plugin-ci validate + ((test -f plugin/patch/${{ inputs.moodle_branch }}.diff && cd /moodle && git am --whitespace=nowarn < ../plugin/patch/${{ inputs.moodle_branch }}.diff) || echo No patch found;) shell: bash - - name: Run savepoints - if: ${{ always() }} - run: moodle-plugin-ci savepoints - shell: bash - - - name: Run mustache - if: ${{ always() && inputs.disable_mustache != 'true' }} - run: moodle-plugin-ci mustache - shell: bash - - name: Run grunt - if: ${{ always() && inputs.disable_grunt != 'true' && inputs.highest_moodle_branch == matrix.moodle-branch }} - run: moodle-plugin-ci grunt - shell: bash - - - name: Run phpunit - if: ${{ always() && inputs.disable_phpunit != 'true' }} - run: | - moodle-plugin-ci phpunit - cd moodle - vendor/bin/phpunit --fail-on-risky --disallow-test-output --filter tool_dataprivacy_metadata_registry_testcase - vendor/bin/phpunit --fail-on-risky --disallow-test-output --testsuite core_privacy_testsuite --filter provider_testcase - shell: bash - - - name: Run behat - if: ${{ always() && inputs.disable_behat != 'true' }} - run: moodle-plugin-ci behat --profile chrome - shell: bash - - - name: PHP Copy/Paste Detector - if: ${{ always() && inputs.disable_phpcpd != 'true' }} - run: moodle-plugin-ci phpcpd - shell: bash - - - name: PHP Mess Detector - if: ${{ always() && inputs.enable_phpmd == 'true' }} - run: moodle-plugin-ci phpmd - shell: bash - - - name: Moodle PHPDoc Checker - if: ${{ always() && inputs.disable_phpdoc != 'true' && inputs.highest_moodle_branch == matrix.moodle-branch }} - # Run this check and only fail CI if it's on 4.0+ / master - run: | - # phpdoc checks - - # Don't stop on faiures - set +e - - # Note this block whilst large, was made so that it can be pasted locally if needed and isn't CI specific - # Disclaimer: you'll need to adjust the main command but otherwise the handling of output remains the same. - output=`GITHUB_PATH=$GITHUB_PATH moodle-plugin-ci phpdoc` - haserrors=$? - - # No errors? Print and return. - if [[ $haserrors -eq 0 ]]; then - echo "phpdoc checks - OK" - exit 0 - fi - - # Skip incorrect errors/warnings and retain the relevant lines. - output=`echo "$output" | grep -v 'Class ( is not documented' | grep -v 'Could not connect to debugging client.'` - output=`echo "$output" | grep -B1 'Line'` - - # Filter out github actions paths from the output. It should only - # show the path relevant to the files in the plugin repo. - # For example: - # from /home/runner/work/moodle-tool_dataflows/moodle-tool_dataflows/moodle/admin/tool/dataflows/db/upgrade.php - # to db/upgrade.php at best, - # or admin/tool/dataflows/db/upgrade.php - currentdir=$(pwd) - if [[ "$output" ]]; then - echo "$output" | sed -e "s,$currentdir/,,g" | sed -e "s,^moodle/,,g" | tee $GITHUB_STEP_SUMMARY - exit 1 - fi - - echo "phpdoc checks - OK" - shell: bash diff --git a/.github/workflows/build-dockerfiles.yml b/.github/workflows/build-dockerfiles.yml new file mode 100644 index 0000000..cbf7083 --- /dev/null +++ b/.github/workflows/build-dockerfiles.yml @@ -0,0 +1,89 @@ +name: Build Dockerfiles + +on: + workflow_dispatch: + push: + branches: + - ci-individual-jobs + paths: + - '.github/actions/matrix/matrix_includes.yml' + - 'docker/**' + - '.github/workflows/build-dockerfiles.yml' + +jobs: + build-matrix: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python (for YAML parsing) + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Install PyYAML + run: pip install pyyaml + + - name: Extract unique moodle-branch/php matrix + id: set-matrix + run: | + import yaml + import json + with open('.github/actions/matrix/matrix_includes.yml') as f: + data = yaml.safe_load(f) + pairs = set((row['moodle-branch'], row['php']) for row in data['include']) + + def container_name(branch, php): + name = f"catalyst-moodle-workflows-{branch}-{php}" + name = name.replace('_', '-').lower() + return f"ghcr.io/catalyst/{name}:latest" + + def find_node(branch, php): + for row in data['include']: + if row['moodle-branch'] == branch and row['php'] == php: + return row.get('node', 20) + return 20 + + matrix = [ + { + 'moodle-branch': b, + 'php': p, + 'node': find_node(b, p), + 'container': container_name(b, p) + } + for b, p in sorted(pairs) + ] + print('::set-output name=matrix::' + json.dumps(matrix)) + shell: python + + build: + name: ${{ matrix.container }} + needs: build-dockerfiles + runs-on: ubuntu-latest + strategy: + matrix: + include: ${{fromJson(needs.build-dockerfiles.outputs.matrix)}} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Build Docker image + run: | + docker build \ + --build-arg MOODLE_BRANCH=${{ matrix.moodle-branch }} \ + --build-arg PHP_VERSION=${{ matrix.php }} \ + --build-arg NODE_VERSION=${{ matrix.node }} \ + -t ${{ matrix.container }} \ + -f docker/Dockerfile docker/ + + - name: Push Docker image to GHCR + run: docker push ${{ matrix.container }} + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c522a30..56c16ed 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,6 +73,7 @@ on: required: false jobs: + pre_job: name: check if job needs to run runs-on: ubuntu-latest @@ -100,6 +101,8 @@ jobs: matrix: ${{ steps.parse-version.outputs.matrix }} component: ${{ steps.parse-version.outputs.component }} highest_moodle_branch: ${{ steps.parse-version.outputs.highest_moodle_branch }} + latest_container: ${{ steps.parse-version.outputs.latest_container }} + latest_pgsql_ver: ${{ steps.parse-version.outputs.latest_pgsql_ver }} release_required: ${{ ( contains(github.event_name, 'push') && steps.check-version.outputs.any_changed == 'true' && @@ -119,7 +122,7 @@ jobs: ) ) }} - echo "::set-output name=publishable::$publishable" + echo "publishable=$publishable" >> $GITHUB_OUTPUT - uses: actions/checkout@v3 - name: Check out CI code uses: actions/checkout@v3 @@ -160,22 +163,108 @@ jobs: disable_master: ${{ inputs.disable_master }} filter: ${{ inputs.moodle_branches }} min_php: ${{ inputs.min_php }} + matrix-unit: + name: ${{ matrix.moodle-branch }} - ${{ matrix.php }} - ${{ matrix.database }} - unit + needs: prepare_matrix + if: needs.pre_job.outputs.should_skip != 'true' && inputs.disable_phpunit != true + strategy: + fail-fast: false + matrix: ${{ fromJson(needs.prepare_matrix.outputs.matrix) }} + env: + IGNORE_PATHS: tests/fixtures + concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.moodle-branch }}-${{ matrix.database }}-${{ matrix.php }}-${{ needs.prepare_matrix.outputs.component }}-unit + cancel-in-progress: true + runs-on: ubuntu-latest + container: + image: ${{ matrix.container }} + services: + pgsql: + image: "postgres:${{ matrix.pgsql-ver }}" + env: + POSTGRES_USER: 'postgres' + POSTGRES_HOST_AUTH_METHOD: 'trust' + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 3 + ports: + - 5432:5432 + mariadb: + image: "mariadb:${{ matrix.mariadb-ver }}" + env: + MYSQL_USER: 'root' + MYSQL_ALLOW_EMPTY_PASSWORD: "true" + MYSQL_CHARACTER_SET_SERVER: "utf8mb4" + MYSQL_COLLATION_SERVER: "utf8mb4_unicode_ci" + ports: + - 3306:3306 + options: >- + --health-cmd="mysqladmin ping" + --health-interval 10s + --health-timeout 5s + --health-retries 3 + steps: + - name: Set custom environment variables + run: | + USER_IGNORE_PATHS="${{ inputs.ignore_paths }}" + if [ -n "${USER_IGNORE_PATHS}" ]; then + IGNORE_PATHS="${IGNORE_PATHS},${USER_IGNORE_PATHS}" + echo "IGNORE_PATHS=${IGNORE_PATHS}" >> $GITHUB_ENV + fi + - name: Check out CI code + uses: actions/checkout@v3 + with: + path: ci + repository: catalyst/catalyst-moodle-workflows + ref: ${{ inputs.internal_workflow_branch }} + token: ${{ github.token }} + - name: Run plugin setup + uses: ./ci/.github/plugin/setup + with: + extra_php_extensions: ${{ inputs.extra_php_extensions }} + extra_plugin_runners: ${{ inputs.extra_plugin_runners }} + moodle_branch: ${{ matrix.moodle-branch }} + - name: Install Moodle and Plugin + # Install moodle, but use our temporary directory to include any potential core patches that have been applied. + run: | + # Install moodle commands + echo "::group::Moodle install output" + # This is a workaround for https://github.com/moodlehq/moodle-plugin-ci/issues/306 - we disable the git repository validation to allow folder cloning. + sed -i '/public function gitUrl($url)/{n; s/{/& return $url;/}' /ci/src/Validate.php - setup: - name: ${{ matrix.moodle-branch }} - ${{ matrix.database }} - php ${{ matrix.php }} - ${{ needs.prepare_matrix.outputs.component }} + moodle-plugin-ci install -vvv --plugin ./plugin --db-host=${{ matrix.database }} --repo /moodle --branch ${{ matrix.moodle-branch }} --db-type ${{ matrix.database }} + + echo "::endgroup::" + shell: bash + - name: Run phpunit + run: | + moodle-plugin-ci phpunit + cd moodle + vendor/bin/phpunit --fail-on-risky --disallow-test-output --filter tool_dataprivacy_metadata_registry_testcase + vendor/bin/phpunit --fail-on-risky --disallow-test-output --testsuite core_privacy_testsuite --filter provider_testcase + shell: bash + matrix-behat: + name: ${{ matrix.moodle-branch }} - ${{ matrix.php }} - ${{ matrix.database }} - behat needs: prepare_matrix - if: needs.pre_job.outputs.should_skip != 'true' + if: needs.pre_job.outputs.should_skip != 'true' && inputs.disable_phpunit != true strategy: fail-fast: false matrix: ${{ fromJson(needs.prepare_matrix.outputs.matrix) }} env: IGNORE_PATHS: tests/fixtures concurrency: - group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.moodle-branch }}-${{ matrix.database }}-${{ matrix.php }}-${{ needs.prepare_matrix.outputs.component }} + group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.moodle-branch }}-${{ matrix.database }}-${{ matrix.php }}-${{ needs.prepare_matrix.outputs.component }}-behat cancel-in-progress: true - runs-on: 'ubuntu-latest' + runs-on: ubuntu-latest + container: + image: ${{ matrix.container }} + options: --user root + volumes: + - /var/run/docker.sock:/var/run/docker.sock # Mount the Docker socket services: - postgres: + pgsql: image: "postgres:${{ matrix.pgsql-ver }}" env: POSTGRES_USER: 'postgres' @@ -219,24 +308,303 @@ jobs: - name: Run plugin setup uses: ./ci/.github/plugin/setup with: - codechecker_max_warnings: ${{ inputs.codechecker_max_warnings }} extra_php_extensions: ${{ inputs.extra_php_extensions }} extra_plugin_runners: ${{ inputs.extra_plugin_runners }} - disable_behat: ${{ inputs.disable_behat }} - disable_grunt: ${{ inputs.disable_grunt }} - disable_mustache: ${{ inputs.disable_mustache }} - disable_phpdoc: ${{ inputs.disable_phpdoc }} - disable_phpcs: ${{ inputs.disable_phpcs }} - disable_phplint: ${{ inputs.disable_phplint }} - disable_phpunit: ${{ inputs.disable_phpunit }} - enable_phpmd: ${{ inputs.enable_phpmd }} - disable_phpcpd: ${{ inputs.disable_phpcpd }} - disable_ci_validate: ${{ inputs.disable_ci_validate }} - highest_moodle_branch: ${{ needs.prepare_matrix.outputs.highest_moodle_branch }} + moodle_branch: ${{ matrix.moodle-branch }} + - name: Install Moodle and Plugin + # Install moodle, but use our temporary directory to include any potential core patches that have been applied. + run: | + # Install moodle commands + echo "::group::Moodle install output" + # This is a workaround for https://github.com/moodlehq/moodle-plugin-ci/issues/306 - we disable the git repository validation to allow folder cloning. + sed -i '/public function gitUrl($url)/{n; s/{/& return $url;/}' /ci/src/Validate.php + + moodle-plugin-ci install -vvv --plugin ./plugin --db-host=${{ matrix.database }} --repo /moodle --branch ${{ matrix.moodle-branch }} --db-type ${{ matrix.database }} + echo "::endgroup::" + shell: bash + - name: Setup behat + shell: bash + run: | + moodle-plugin-ci add-config '$CFG->behat_wwwroot = "http://selenium:4444";' + - name: Run behat + if: ${{ inputs.disable_behat != true }} + run: moodle-plugin-ci behat --profile chrome + shell: bash + codechecker: + if: needs.pre_job.outputs.should_skip != 'true' + runs-on: ubuntu-latest + container: + image: ${{ needs.prepare_matrix.outputs.latest_container }} + needs: prepare_matrix + steps: + - name: Check out CI code + uses: actions/checkout@v3 + with: + path: ci + repository: catalyst/catalyst-moodle-workflows + ref: ${{ inputs.internal_workflow_branch }} + token: ${{ github.token }} + - name: Run plugin setup (canonical) + uses: ./ci/.github/plugin/setup + with: + extra_php_extensions: ${{ inputs.extra_php_extensions }} + extra_plugin_runners: ${{ inputs.extra_plugin_runners }} + moodle_branch: ${{ needs.prepare_matrix.outputs.highest_moodle_branch }} + - name: Run codechecker + if: ${{ inputs.disable_phpcs != true }} + run: moodle-plugin-ci codechecker --max-warnings=${{ inputs.codechecker_max_warnings }} ./plugin + shell: bash + phplint: + if: needs.pre_job.outputs.should_skip != 'true' + runs-on: ubuntu-latest + container: + image: ${{ needs.prepare_matrix.outputs.latest_container }} + needs: prepare_matrix + steps: + - name: Check out CI code + uses: actions/checkout@v3 + with: + path: ci + repository: catalyst/catalyst-moodle-workflows + ref: ${{ inputs.internal_workflow_branch }} + token: ${{ github.token }} + - name: Run plugin setup (canonical) + uses: ./ci/.github/plugin/setup + with: + extra_php_extensions: ${{ inputs.extra_php_extensions }} + extra_plugin_runners: ${{ inputs.extra_plugin_runners }} + moodle_branch: ${{ needs.prepare_matrix.outputs.highest_moodle_branch }} + - name: Run phplint + if: ${{ inputs.disable_phplint != true }} + run: moodle-plugin-ci phplint ./plugin + shell: bash + validate: + if: needs.pre_job.outputs.should_skip != 'true' + runs-on: ubuntu-latest + container: + image: ${{ needs.prepare_matrix.outputs.latest_container }} + needs: prepare_matrix + services: + pgsql: + image: "postgres:${{ needs.prepare_matrix.outputs.latest_pgsql_ver }}" + env: + POSTGRES_USER: 'postgres' + POSTGRES_HOST_AUTH_METHOD: 'trust' + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 3 + ports: + - 5432:5432 + steps: + - name: Check out CI code + uses: actions/checkout@v3 + with: + path: ci + repository: catalyst/catalyst-moodle-workflows + ref: ${{ inputs.internal_workflow_branch }} + token: ${{ github.token }} + - name: Run plugin setup (canonical) + uses: ./ci/.github/plugin/setup + with: + extra_php_extensions: ${{ inputs.extra_php_extensions }} + extra_plugin_runners: ${{ inputs.extra_plugin_runners }} + moodle_branch: ${{ needs.prepare_matrix.outputs.highest_moodle_branch }} + - name: Install Moodle and Plugin + # Install moodle, but use our temporary directory to include any potential core patches that have been applied. + run: | + # Install moodle commands + echo "::group::Moodle install output" + # This is a workaround for https://github.com/moodlehq/moodle-plugin-ci/issues/306 - we disable the git repository validation to allow folder cloning. + sed -i '/public function gitUrl($url)/{n; s/{/& return $url;/}' /ci/src/Validate.php + + moodle-plugin-ci install -vvv --plugin ./plugin --db-host=pgsql --repo /moodle --branch ${{ needs.prepare_matrix.outputs.highest_moodle_branch }} --db-type pgsql + + echo "::endgroup::" + - name: Run validate + if: ${{ inputs.disable_ci_validate != true }} + run: moodle-plugin-ci validate ./plugin + shell: bash + savepoints: + name: Savepoints + if: needs.pre_job.outputs.should_skip != 'true' + runs-on: ubuntu-latest + container: + image: ${{ needs.prepare_matrix.outputs.latest_container }} + needs: prepare_matrix + steps: + - name: Check out CI code + uses: actions/checkout@v3 + with: + path: ci + repository: catalyst/catalyst-moodle-workflows + ref: ${{ inputs.internal_workflow_branch }} + token: ${{ github.token }} + - name: Run plugin setup (canonical) + uses: ./ci/.github/plugin/setup + with: + extra_php_extensions: ${{ inputs.extra_php_extensions }} + extra_plugin_runners: ${{ inputs.extra_plugin_runners }} + moodle_branch: ${{ needs.prepare_matrix.outputs.highest_moodle_branch }} + - name: Run savepoints + run: moodle-plugin-ci savepoints ./plugin + shell: bash + mustache: + if: needs.pre_job.outputs.should_skip != 'true' + runs-on: ubuntu-latest + container: + image: ${{ needs.prepare_matrix.outputs.latest_container }} + needs: prepare_matrix + services: + pgsql: + image: "postgres:${{ needs.prepare_matrix.outputs.latest_pgsql_ver }}" + env: + POSTGRES_USER: 'postgres' + POSTGRES_HOST_AUTH_METHOD: 'trust' + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 3 + ports: + - 5432:5432 + steps: + - name: Check out CI code + uses: actions/checkout@v3 + with: + path: ci + repository: catalyst/catalyst-moodle-workflows + ref: ${{ inputs.internal_workflow_branch }} + token: ${{ github.token }} + - name: Run plugin setup (canonical) + uses: ./ci/.github/plugin/setup + with: + extra_php_extensions: ${{ inputs.extra_php_extensions }} + extra_plugin_runners: ${{ inputs.extra_plugin_runners }} + moodle_branch: ${{ needs.prepare_matrix.outputs.highest_moodle_branch }} + - name: Install Moodle and Plugin + # Install moodle, but use our temporary directory to include any potential core patches that have been applied. + run: | + # Install moodle commands + echo "::group::Moodle install output" + # This is a workaround for https://github.com/moodlehq/moodle-plugin-ci/issues/306 - we disable the git repository validation to allow folder cloning. + sed -i '/public function gitUrl($url)/{n; s/{/& return $url;/}' /ci/src/Validate.php + + moodle-plugin-ci install -vvv --plugin ./plugin --db-host=pgsql --repo /moodle --branch ${{ needs.prepare_matrix.outputs.highest_moodle_branch }} --db-type pgsql + + echo "::endgroup::" + - name: Run mustache + if: ${{ inputs.disable_mustache != true }} + run: moodle-plugin-ci mustache + shell: bash + grunt: + if: needs.pre_job.outputs.should_skip != 'true' + runs-on: ubuntu-latest + container: + image: ${{ needs.prepare_matrix.outputs.latest_container }} + needs: prepare_matrix + steps: + - name: Check out CI code + uses: actions/checkout@v3 + with: + path: ci + repository: catalyst/catalyst-moodle-workflows + ref: ${{ inputs.internal_workflow_branch }} + token: ${{ github.token }} + - name: Run plugin setup (canonical) + uses: ./ci/.github/plugin/setup + with: + extra_php_extensions: ${{ inputs.extra_php_extensions }} + extra_plugin_runners: ${{ inputs.extra_plugin_runners }} + moodle_branch: ${{ needs.prepare_matrix.outputs.highest_moodle_branch }} + - name: Run grunt + if: ${{ inputs.disable_grunt != true }} + run: | + cd /moodle + npm install + cd - + moodle-plugin-ci grunt --moodle /moodle --no-interaction -vvv ./plugin + shell: bash + phpmd: + if: needs.pre_job.outputs.should_skip != 'true' + runs-on: ubuntu-latest + container: + image: ${{ needs.prepare_matrix.outputs.latest_container }} + needs: prepare_matrix + steps: + - name: Check out CI code + uses: actions/checkout@v3 + with: + path: ci + repository: catalyst/catalyst-moodle-workflows + ref: ${{ inputs.internal_workflow_branch }} + token: ${{ github.token }} + - name: Run plugin setup (canonical) + uses: ./ci/.github/plugin/setup + with: + extra_php_extensions: ${{ inputs.extra_php_extensions }} + extra_plugin_runners: ${{ inputs.extra_plugin_runners }} + moodle_branch: ${{ needs.prepare_matrix.outputs.highest_moodle_branch }} + - name: Run phpmd + if: ${{ inputs.enable_phpmd == true }} + run: moodle-plugin-ci phpmd ./plugin + shell: bash + phpdoc: + if: needs.pre_job.outputs.should_skip != 'true' + runs-on: ubuntu-latest + container: + image: ${{ needs.prepare_matrix.outputs.latest_container }} + needs: prepare_matrix + steps: + - name: Check out CI code + uses: actions/checkout@v3 + with: + path: ci + repository: catalyst/catalyst-moodle-workflows + ref: ${{ inputs.internal_workflow_branch }} + token: ${{ github.token }} + - name: Run plugin setup (canonical) + uses: ./ci/.github/plugin/setup + with: + extra_php_extensions: ${{ inputs.extra_php_extensions }} + extra_plugin_runners: ${{ inputs.extra_plugin_runners }} + moodle_branch: ${{ needs.prepare_matrix.outputs.highest_moodle_branch }} + - name: Run phpdoc + if: ${{ inputs.disable_phpdoc != true }} + run: | + set +e + output=`GITHUB_PATH=$GITHUB_PATH moodle-plugin-ci phpdoc ./plugin` + haserrors=$? + if [[ $haserrors -eq 0 ]]; then + echo "phpdoc checks - OK" + exit 0 + fi + output=`echo "$output" | grep -v 'Class ( is not documented' | grep -v 'Could not connect to debugging client.'` + output=`echo "$output" | grep -B1 'Line'` + currentdir=$(pwd) + if [[ "$output" ]]; then + echo "$output" | sed -e "s,$currentdir/,,g" | sed -e "s,^moodle/,,g" | tee $GITHUB_STEP_SUMMARY + exit 1 + fi + echo "phpdoc checks - OK" + shell: bash release: name: Release to the Moodle plugin directory - needs: [setup, prepare_matrix] + needs: + - pre_job + - prepare_matrix + - matrix-unit + - matrix-behat + - codechecker + - phplint + - validate + - savepoints + - mustache + - grunt + - phpmd + - phpdoc # If it matches a standard branch naming convention, it should permit a # release to happen, otherwise this step should be skipped. # Patterns allowed: @@ -253,7 +621,7 @@ jobs: env: SECRET_TO_CHECK: '${{ secrets.moodle_org_token }}' if: ${{ env.SECRET_TO_CHECK != '' }} - run: echo "::set-output name=has-secrets::true" + run: echo "has-secrets=true" >> $GITHUB_OUTPUT - name: Check out CI code uses: actions/checkout@v3 diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..a04da81 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,61 @@ + +FROM ubuntu:24.04 + +ARG MOODLE_BRANCH +ARG PHP_VERSION +ARG NODE_VERSION + +# Install dependencies +RUN apt-get update && \ + apt-get install -y lsb-release ca-certificates apt-transport-https software-properties-common curl + +# Add the official PHP repository +RUN add-apt-repository ppa:ondrej/php + +# Install the specified PHP version and common extensions +RUN apt-get update && \ + apt-get install -y php${PHP_VERSION} php${PHP_VERSION}-cli php${PHP_VERSION}-xml php${PHP_VERSION}-mbstring php${PHP_VERSION}-zip php${PHP_VERSION}-pgsql php${PHP_VERSION}-mysql php${PHP_VERSION}-gd php${PHP_VERSION}-soap php${PHP_VERSION}-xmlrpc php${PHP_VERSION}-curl php${PHP_VERSION}-intl + + +# Symlink for default 'php' command +RUN update-alternatives --set php /usr/bin/php${PHP_VERSION} + +# Set PHP max_input_vars to at least 5000 for CLI and FPM (if installed) +RUN echo 'max_input_vars=5000' > /etc/php/${PHP_VERSION}/cli/conf.d/99-max-input-vars.ini \ + && if [ -d "/etc/php/${PHP_VERSION}/fpm/conf.d" ]; then \ + cp /etc/php/${PHP_VERSION}/cli/conf.d/99-max-input-vars.ini /etc/php/${PHP_VERSION}/fpm/conf.d/; \ + fi + + +# Install Node.js (specific version) and other dependencies +RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - +RUN apt-get install -y nodejs git unzip curl locales postgresql mariadb-client +RUN locale-gen en_AU.UTF-8 + +# Install Composer (official recommended method) +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer + +# Clone Moodle core (example: main branch) +RUN git clone --depth 1 --branch ${MOODLE_BRANCH} https://github.com/moodle/moodle.git /moodle + +# Install moodle-plugin-ci +RUN composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci /ci ^4 + +# Install Grunt CLI globally +RUN npm install -g grunt-cli + +# Install Docker CLI for behat +RUN apt-get update && apt-get install -y docker.io + +# Add ci/bin and ci/vendor/bin to PATH +ENV PATH="/ci/bin:/ci/vendor/bin:${PATH}" + +RUN mkdir -p /workspace + +# Set working directory +WORKDIR /workspace + +# Example: Set build args as environment variables +ENV MOODLE_BRANCH=${MOODLE_BRANCH} +ENV PHP_VERSION=${PHP_VERSION} +ENV NODE_VERSION=${NODE_VERSION} \ No newline at end of file