From 76c46b5c759fb7a8148d4c528ef350a712f75982 Mon Sep 17 00:00:00 2001 From: Phillip Davis Date: Thu, 26 Mar 2026 16:34:48 +0930 Subject: [PATCH 1/6] chore(ci): port CI from drone to GitHub workflows and bump PHP to 8.3, and core to 11. --- .drone.star | 2084 ----------------- .github/workflows/main.yml | 56 + appinfo/app.php | 36 +- appinfo/info.xml | 3 +- composer.json | 2 +- composer.lock | 661 +++--- controller/preview.php | 2 +- templates/index.php | 2 +- templates/part.content.php | 28 +- templates/part.filenotfounderror.php | 4 +- templates/part.internalservererror.php | 4 +- templates/part.linkerror.php | 4 +- templates/public.php | 36 +- .../middleware/EnvCheckMiddlewareTest.php | 4 +- vendor-bin/owncloud-codestyle/composer.json | 2 +- 15 files changed, 434 insertions(+), 2494 deletions(-) delete mode 100644 .drone.star create mode 100644 .github/workflows/main.yml diff --git a/.drone.star b/.drone.star deleted file mode 100644 index 6279e9ff5c..0000000000 --- a/.drone.star +++ /dev/null @@ -1,2084 +0,0 @@ -BANST_AWS_CLI = "banst/awscli" -INBUCKET_INBUCKET = "inbucket/inbucket" -MINIO_MC = "minio/mc:RELEASE.2020-12-18T10-53-53Z" -OC_CI_ALPINE = "owncloudci/alpine:latest" -OC_CI_BAZEL_BUILDIFIER = "owncloudci/bazel-buildifier" -OC_CI_CEPH = "owncloudci/ceph:tag-build-master-jewel-ubuntu-16.04" -OC_CI_CORE = "owncloudci/core" -OC_CI_DRONE_SKIP_PIPELINE = "owncloudci/drone-skip-pipeline" -OC_CI_NODEJS = "owncloudci/nodejs:%s" -OC_CI_ORACLE_XE = "owncloudci/oracle-xe:latest" -OC_CI_PHP = "owncloudci/php:%s" -OC_CI_SCALITY_S3_SERVER = "owncloudci/scality-s3server" -OC_CI_WAIT_FOR = "owncloudci/wait-for:latest" -OC_OPS_ELASTIC_SEARCH = "owncloudops/elasticsearch:%s" -OC_UBUNTU = "owncloud/ubuntu:20.04" -OSIXIA_OPEN_LDAP = "osixia/openldap" -PLUGINS_GITHUB_RELEASE = "plugins/github-release" -PLUGINS_S3 = "plugins/s3" -PLUGINS_S3_CACHE = "plugins/s3-cache:1" -SELENIUM_STANDALONE_CHROME_DEBUG = "selenium/standalone-chrome-debug:3.141.59-oxygen" -SELENIUM_STANDALONE_FIREFOX_DEBUG = "selenium/standalone-firefox-debug:3.8.1" -SONARSOURCE_SONAR_SCANNER_CLI = "sonarsource/sonar-scanner-cli" - -DEFAULT_PHP_VERSION = "7.4" -DEFAULT_NODEJS_VERSION = "14" - -# minio mc environment variables -MINIO_MC_ENV = { - "CACHE_BUCKET": { - "from_secret": "cache_s3_bucket", - }, - "MC_HOST": { - "from_secret": "cache_s3_server", - }, - "AWS_ACCESS_KEY_ID": { - "from_secret": "cache_s3_access_key", - }, - "AWS_SECRET_ACCESS_KEY": { - "from_secret": "cache_s3_secret_key", - }, -} - -dir = { - "base": "/var/www/owncloud", - "federated": "/var/www/owncloud/federated", - "server": "/var/www/owncloud/server", - "testrunner": "/var/www/owncloud/testrunner", - "scalityConfig": "/var/www/owncloud/server/config/scality.config.php", - "browserService": "/home/seluser/Downloads", -} - -config = { - "branches": [ - "master", - ], - "appInstallCommandPhp": "composer install", - "codestyle": True, - "phpstan": False, - "phan": False, - "javascript": False, - "phpunit": { - "reducedDatabases": { - "phpVersions": [ - DEFAULT_PHP_VERSION, - ], - "databases": [ - "sqlite", - "mariadb:10.2", - "mysql:8.0", - "postgres:9.4", - ], - "coverage": False, - }, - }, - "acceptance": False, -} - -def main(ctx): - before = beforePipelines(ctx) - - coverageTests = coveragePipelines(ctx) - if (coverageTests == False): - print("Errors detected in coveragePipelines. Review messages above.") - return [] - - dependsOn(before, coverageTests) - - nonCoverageTests = nonCoveragePipelines(ctx) - if (nonCoverageTests == False): - print("Errors detected in nonCoveragePipelines. Review messages above.") - return [] - - dependsOn(before, nonCoverageTests) - - stages = stagePipelines(ctx) - if (stages == False): - print("Errors detected. Review messages above.") - return [] - - dependsOn(before, stages) - - if (coverageTests == []): - afterCoverageTests = [] - else: - afterCoverageTests = afterCoveragePipelines(ctx) - dependsOn(coverageTests, afterCoverageTests) - - return before + coverageTests + afterCoverageTests + nonCoverageTests + stages - -def beforePipelines(ctx): - return codestyle(ctx) + jscodestyle(ctx) + phpstan(ctx) + phan(ctx) + phplint(ctx) + checkStarlark() - -def coveragePipelines(ctx): - # All unit test pipelines that have coverage or other test analysis reported - jsPipelines = javascript(ctx, True) - phpUnitPipelines = phpTests(ctx, "phpunit", True) - phpIntegrationPipelines = phpTests(ctx, "phpintegration", True) - if (jsPipelines == False) or (phpUnitPipelines == False) or (phpIntegrationPipelines == False): - return False - - return jsPipelines + phpUnitPipelines + phpIntegrationPipelines - -def nonCoveragePipelines(ctx): - # All unit test pipelines that do not have coverage or other test analysis reported - jsPipelines = javascript(ctx, False) - phpUnitPipelines = phpTests(ctx, "phpunit", False) - phpIntegrationPipelines = phpTests(ctx, "phpintegration", False) - if (jsPipelines == False) or (phpUnitPipelines == False) or (phpIntegrationPipelines == False): - return False - - return jsPipelines + phpUnitPipelines + phpIntegrationPipelines - -def stagePipelines(ctx): - buildPipelines = build(ctx) - acceptancePipelines = acceptance(ctx) - if (buildPipelines == False) or (acceptancePipelines == False): - return False - - return buildPipelines + acceptancePipelines - -def afterCoveragePipelines(ctx): - return [ - sonarAnalysis(ctx), - ] - -def codestyle(ctx): - pipelines = [] - - if "codestyle" not in config: - return pipelines - - default = { - "phpVersions": [DEFAULT_PHP_VERSION], - } - - if "defaults" in config: - if "codestyle" in config["defaults"]: - for item in config["defaults"]["codestyle"]: - default[item] = config["defaults"]["codestyle"][item] - - codestyleConfig = config["codestyle"] - - if type(codestyleConfig) == "bool": - if codestyleConfig: - # the config has "codestyle" true, so specify an empty dict that will get the defaults - codestyleConfig = {} - else: - return pipelines - - if len(codestyleConfig) == 0: - # "codestyle" is an empty dict, so specify a single section that will get the defaults - codestyleConfig = {"doDefault": {}} - - for category, matrix in codestyleConfig.items(): - params = {} - for item in default: - params[item] = matrix[item] if item in matrix else default[item] - - for phpVersion in params["phpVersions"]: - name = "coding-standard-php%s" % phpVersion - - result = { - "kind": "pipeline", - "type": "docker", - "name": name, - "workspace": { - "base": dir["base"], - "path": "server/apps/%s" % ctx.repo.name, - }, - "steps": skipIfUnchanged(ctx, "lint") + - [ - { - "name": "coding-standard", - "image": OC_CI_PHP % phpVersion, - "commands": [ - "make test-php-style", - ], - }, - ], - "depends_on": [], - "trigger": { - "ref": [ - "refs/pull/**", - "refs/tags/**", - ], - }, - } - - for branch in config["branches"]: - result["trigger"]["ref"].append("refs/heads/%s" % branch) - - pipelines.append(result) - - return pipelines - -def jscodestyle(ctx): - pipelines = [] - - if "jscodestyle" not in config: - return pipelines - - if type(config["jscodestyle"]) == "bool": - if not config["jscodestyle"]: - return pipelines - - result = { - "kind": "pipeline", - "type": "docker", - "name": "coding-standard-js", - "workspace": { - "base": dir["base"], - "path": "server/apps/%s" % ctx.repo.name, - }, - "steps": skipIfUnchanged(ctx, "lint") + - [ - { - "name": "coding-standard-js", - "image": OC_CI_NODEJS % DEFAULT_NODEJS_VERSION, - "commands": [ - "make test-js-style", - ], - }, - ], - "depends_on": [], - "trigger": { - "ref": [ - "refs/pull/**", - "refs/tags/**", - ], - }, - } - - for branch in config["branches"]: - result["trigger"]["ref"].append("refs/heads/%s" % branch) - - pipelines.append(result) - - return pipelines - -def phpstan(ctx): - pipelines = [] - - if "phpstan" not in config: - return pipelines - - default = { - "phpVersions": [DEFAULT_PHP_VERSION], - "logLevel": "2", - "extraApps": {}, - "enableApp": True, - } - - if "defaults" in config: - if "phpstan" in config["defaults"]: - for item in config["defaults"]["phpstan"]: - default[item] = config["defaults"]["phpstan"][item] - - phpstanConfig = config["phpstan"] - - if type(phpstanConfig) == "bool": - if phpstanConfig: - # the config has "phpstan" true, so specify an empty dict that will get the defaults - phpstanConfig = {} - else: - return pipelines - - if len(phpstanConfig) == 0: - # "phpstan" is an empty dict, so specify a single section that will get the defaults - phpstanConfig = {"doDefault": {}} - - for category, matrix in phpstanConfig.items(): - params = {} - for item in default: - params[item] = matrix[item] if item in matrix else default[item] - - for phpVersion in params["phpVersions"]: - name = "phpstan-php%s" % phpVersion - - result = { - "kind": "pipeline", - "type": "docker", - "name": name, - "workspace": { - "base": dir["base"], - "path": "server/apps/%s" % ctx.repo.name, - }, - "steps": skipIfUnchanged(ctx, "lint") + - installCore(ctx, "daily-master-qa", "sqlite", False) + - installAppPhp(ctx, phpVersion) + - installExtraApps(phpVersion, params["extraApps"]) + - setupServerAndApp(ctx, phpVersion, params["logLevel"], False, params["enableApp"]) + - [ - { - "name": "phpstan", - "image": OC_CI_PHP % phpVersion, - "commands": [ - "make test-php-phpstan", - ], - }, - ], - "depends_on": [], - "trigger": { - "ref": [ - "refs/pull/**", - "refs/tags/**", - ], - }, - } - - for branch in config["branches"]: - result["trigger"]["ref"].append("refs/heads/%s" % branch) - - pipelines.append(result) - - return pipelines - -def phan(ctx): - pipelines = [] - - if "phan" not in config: - return pipelines - - default = { - "phpVersions": [DEFAULT_PHP_VERSION], - } - - if "defaults" in config: - if "phan" in config["defaults"]: - for item in config["defaults"]["phan"]: - default[item] = config["defaults"]["phan"][item] - - phanConfig = config["phan"] - - if type(phanConfig) == "bool": - if phanConfig: - # the config has "phan" true, so specify an empty dict that will get the defaults - phanConfig = {} - else: - return pipelines - - if len(phanConfig) == 0: - # "phan" is an empty dict, so specify a single section that will get the defaults - phanConfig = {"doDefault": {}} - - for category, matrix in phanConfig.items(): - params = {} - for item in default: - params[item] = matrix[item] if item in matrix else default[item] - - for phpVersion in params["phpVersions"]: - name = "phan-php%s" % phpVersion - - result = { - "kind": "pipeline", - "type": "docker", - "name": name, - "workspace": { - "base": dir["base"], - "path": "server/apps/%s" % ctx.repo.name, - }, - "steps": skipIfUnchanged(ctx, "lint") + - installCore(ctx, "daily-master-qa", "sqlite", False) + - [ - { - "name": "phan", - "image": OC_CI_PHP % phpVersion, - "commands": [ - "make test-php-phan", - ], - }, - ], - "depends_on": [], - "trigger": { - "ref": [ - "refs/pull/**", - "refs/tags/**", - ], - }, - } - - for branch in config["branches"]: - result["trigger"]["ref"].append("refs/heads/%s" % branch) - - pipelines.append(result) - - return pipelines - -def build(ctx): - pipelines = [] - - if "build" not in config: - return pipelines - - default = { - "phpVersions": [DEFAULT_PHP_VERSION], - "commands": [ - "make dist", - ], - "extraEnvironment": {}, - "configureTarOnTag": False, - } - - if "defaults" in config: - if "build" in config["defaults"]: - for item in config["defaults"]["build"]: - default[item] = config["defaults"]["build"][item] - - matrix = config["build"] - - if type(matrix) == "bool": - if matrix: - # the config has "build" true, so specify an empty dict that will get the defaults - matrix = {} - else: - return pipelines - - params = {} - for item in default: - params[item] = matrix[item] if item in matrix else default[item] - - for phpVersion in params["phpVersions"]: - result = { - "kind": "pipeline", - "type": "docker", - "name": "build", - "workspace": { - "base": dir["base"], - "path": "server/apps/%s" % ctx.repo.name, - }, - "steps": [ - { - "name": "build", - "image": OC_CI_PHP % phpVersion, - "environment": params["extraEnvironment"], - "commands": params["commands"], - }, - ] + ([ - { - "name": "github_release", - "image": PLUGINS_GITHUB_RELEASE, - "settings": { - "checksum": "sha256", - "file_exists": "overwrite", - "files": "build/dist/%s.tar.gz" % ctx.repo.name, - "prerelease": True, - }, - "environment": { - "GITHUB_TOKEN": { - "from_secret": "github_token", - }, - }, - "when": { - "event": [ - "tag", - ], - }, - }, - ] if params["configureTarOnTag"] else []), - "depends_on": [], - "trigger": { - "ref": [ - "refs/pull/**", - "refs/tags/**", - ], - }, - } - - for branch in config["branches"]: - result["trigger"]["ref"].append("refs/heads/%s" % branch) - - pipelines.append(result) - - return pipelines - -def javascript(ctx, withCoverage): - pipelines = [] - - if "javascript" not in config: - return pipelines - - default = { - "coverage": False, - "logLevel": "2", - "extraSetup": [], - "extraServices": [], - "extraEnvironment": {}, - "extraCommandsBeforeTestRun": [], - "extraTeardown": [], - "skip": False, - "enableApp": True, - } - - if "defaults" in config: - if "javascript" in config["defaults"]: - for item in config["defaults"]["javascript"]: - default[item] = config["defaults"]["javascript"][item] - - matrix = config["javascript"] - - if type(matrix) == "bool": - if matrix: - # the config has "javascript" true, so specify an empty dict that will get the defaults - matrix = {} - else: - return pipelines - - params = {} - for item in default: - params[item] = matrix[item] if item in matrix else default[item] - - if params["skip"]: - return pipelines - - # if we only want pipelines with coverage, and this pipeline does not do coverage, then do not include it - if withCoverage and not params["coverage"]: - return pipelines - - # if we only want pipelines without coverage, and this pipeline does coverage, then do not include it - if not withCoverage and params["coverage"]: - return pipelines - - result = { - "kind": "pipeline", - "type": "docker", - "name": "javascript-tests", - "workspace": { - "base": dir["base"], - "path": "server/apps/%s" % ctx.repo.name, - }, - "steps": skipIfUnchanged(ctx, "unit-tests") + - installCore(ctx, "daily-master-qa", "sqlite", False) + - installAppJavaScript(ctx) + - setupServerAndApp(ctx, DEFAULT_PHP_VERSION, params["logLevel"], False, params["enableApp"]) + - params["extraSetup"] + - [ - { - "name": "js-tests", - "image": OC_CI_NODEJS % getNodeJsVersion(), - "environment": params["extraEnvironment"], - "commands": params["extraCommandsBeforeTestRun"] + [ - "make test-js", - ], - }, - ] + params["extraTeardown"], - "services": params["extraServices"], - "depends_on": [], - "trigger": { - "ref": [ - "refs/pull/**", - "refs/tags/**", - ], - }, - } - - if params["coverage"]: - result["steps"].append({ - "name": "coverage-cache", - "image": PLUGINS_S3, - "settings": { - "endpoint": { - "from_secret": "cache_s3_server", - }, - "bucket": "cache", - "source": "./coverage/lcov.info", - "target": "%s/%s" % (ctx.repo.slug, ctx.build.commit + "-${DRONE_BUILD_NUMBER}"), - "path_style": True, - "strip_prefix": "./coverage", - "access_key": { - "from_secret": "cache_s3_access_key", - }, - "secret_key": { - "from_secret": "cache_s3_secret_key", - }, - }, - }) - - for branch in config["branches"]: - result["trigger"]["ref"].append("refs/heads/%s" % branch) - - return [result] - -def phpTests(ctx, testType, withCoverage): - pipelines = [] - - if testType not in config: - return pipelines - - errorFound = False - - # The default PHP unit test settings for a PR. - # Note: do not run Oracle by default in PRs. - prDefault = { - "phpVersions": [DEFAULT_PHP_VERSION], - "servers": ["daily-master-qa"], - "databases": [ - "sqlite", - "mariadb:10.2", - "mysql:8.0", - "postgres:9.4", - ], - "coverage": True, - "includeKeyInMatrixName": False, - "logLevel": "2", - "cephS3": False, - "scalityS3": False, - "extraSetup": [], - "extraServices": [], - "extraEnvironment": {}, - "extraCommandsBeforeTestRun": [], - "extraApps": {}, - "extraTeardown": [], - "skip": False, - "enableApp": True, - } - - # The default PHP unit test settings for the cron job (usually runs nightly). - cronDefault = { - "phpVersions": [DEFAULT_PHP_VERSION], - "servers": ["daily-master-qa"], - "databases": [ - "sqlite", - "mariadb:10.2", - "mysql:8.0", - "postgres:9.4", - "oracle", - ], - "coverage": True, - "includeKeyInMatrixName": False, - "logLevel": "2", - "cephS3": False, - "scalityS3": False, - "extraSetup": [], - "extraServices": [], - "extraEnvironment": {}, - "extraCommandsBeforeTestRun": [], - "extraApps": {}, - "extraTeardown": [], - "skip": False, - "enableApp": True, - } - - if (ctx.build.event == "cron"): - default = cronDefault - else: - default = prDefault - - if "defaults" in config: - if testType in config["defaults"]: - for item in config["defaults"][testType]: - default[item] = config["defaults"][testType][item] - - phpTestConfig = config[testType] - - if type(phpTestConfig) == "bool": - if phpTestConfig: - # the config has just True, so specify an empty dict that will get the defaults - phpTestConfig = {} - else: - return pipelines - - if len(phpTestConfig) == 0: - # the PHP test config is an empty dict, so specify a single section that will get the defaults - phpTestConfig = {"doDefault": {}} - - for category, matrix in phpTestConfig.items(): - params = {} - for item in default: - params[item] = matrix[item] if item in matrix else default[item] - - if params["skip"]: - continue - - # if we only want pipelines with coverage, and this pipeline does not do coverage, then do not include it - if withCoverage and not params["coverage"]: - continue - - # if we only want pipelines without coverage, and this pipeline does coverage, then do not include it - if not withCoverage and params["coverage"]: - continue - - cephS3Params = params["cephS3"] - if type(cephS3Params) == "bool": - cephS3Needed = cephS3Params - filesPrimaryS3NeededForCeph = cephS3Params - else: - cephS3Needed = True - filesPrimaryS3NeededForCeph = cephS3Params["filesPrimaryS3Needed"] if "filesPrimaryS3Needed" in cephS3Params else True - - scalityS3Params = params["scalityS3"] - if type(scalityS3Params) == "bool": - scalityS3Needed = scalityS3Params - filesPrimaryS3NeededForScality = scalityS3Params - else: - scalityS3Needed = True - filesPrimaryS3NeededForScality = scalityS3Params["filesPrimaryS3Needed"] if "filesPrimaryS3Needed" in scalityS3Params else True - - if ((ctx.repo.name != "files_primary_s3") and (filesPrimaryS3NeededForCeph or filesPrimaryS3NeededForScality)): - # If we are not already "files_primary_s3" and we need S3 storage, then install the "files_primary_s3" app - extraAppsDict = { - "files_primary_s3": "composer install", - } - for app, command in params["extraApps"].items(): - extraAppsDict[app] = command - params["extraApps"] = extraAppsDict - - for phpVersion in params["phpVersions"]: - if testType == "phpunit": - if params["coverage"]: - command = "make test-php-unit-dbg" - else: - command = "make test-php-unit" - elif params["coverage"]: - command = "make test-php-integration-dbg" - else: - command = "make test-php-integration" - - # Get the first 3 characters of the PHP version (7.4 or 8.0 etc) - # And use that for constructing the pipeline name - # That helps shorten pipeline names when using owncloud-ci images - # that have longer names like 7.4-ubuntu20.04 - phpVersionForPipelineName = phpVersion[0:3] - - for server in params["servers"]: - for db in params["databases"]: - keyString = "-" + category if params["includeKeyInMatrixName"] else "" - if len(params["servers"]) > 1: - serverString = "-%s" % server.replace("daily-", "").replace("-qa", "") - else: - serverString = "" - name = "%s%s-php%s%s-%s" % (testType, keyString, phpVersionForPipelineName, serverString, db.replace(":", "")) - maxLength = 50 - nameLength = len(name) - if nameLength > maxLength: - print("Error: generated phpunit stage name of length", nameLength, "is not supported. The maximum length is " + str(maxLength) + ".", name) - errorFound = True - - result = { - "kind": "pipeline", - "type": "docker", - "name": name, - "workspace": { - "base": dir["base"], - "path": "server/apps/%s" % ctx.repo.name, - }, - "steps": skipIfUnchanged(ctx, "unit-tests") + - installCore(ctx, server, db, False) + - installAppPhp(ctx, phpVersion) + - installExtraApps(phpVersion, params["extraApps"]) + - setupServerAndApp(ctx, phpVersion, params["logLevel"], False, params["enableApp"]) + - setupCeph(params["cephS3"]) + - setupScality(params["scalityS3"]) + - params["extraSetup"] + - [ - { - "name": "%s-tests" % testType, - "image": OC_CI_PHP % phpVersion, - "environment": params["extraEnvironment"], - "commands": params["extraCommandsBeforeTestRun"] + [ - command, - ], - }, - ] + params["extraTeardown"], - "services": databaseService(db) + - cephService(params["cephS3"]) + - scalityService(params["scalityS3"]) + - params["extraServices"], - "depends_on": [], - "trigger": { - "ref": [ - "refs/pull/**", - "refs/tags/**", - ], - }, - } - - if params["coverage"]: - result["steps"].append({ - "name": "coverage-rename", - "image": OC_CI_PHP % phpVersion, - "commands": [ - "mv tests/output/clover.xml tests/output/clover-%s.xml" % (name), - ], - }) - result["steps"].append({ - "name": "coverage-cache-1", - "image": PLUGINS_S3, - "settings": { - "endpoint": { - "from_secret": "cache_s3_server", - }, - "bucket": "cache", - "source": "tests/output/clover-%s.xml" % (name), - "target": "%s/%s" % (ctx.repo.slug, ctx.build.commit + "-${DRONE_BUILD_NUMBER}"), - "path_style": True, - "strip_prefix": "tests/output", - "access_key": { - "from_secret": "cache_s3_access_key", - }, - "secret_key": { - "from_secret": "cache_s3_secret_key", - }, - }, - }) - - for branch in config["branches"]: - result["trigger"]["ref"].append("refs/heads/%s" % branch) - - pipelines.append(result) - - if errorFound: - return False - - return pipelines - -def acceptance(ctx): - pipelines = [] - - if "acceptance" not in config: - return pipelines - - if type(config["acceptance"]) == "bool": - if not config["acceptance"]: - return pipelines - - errorFound = False - - default = { - "servers": ["daily-master-qa", "latest"], - "browsers": ["chrome"], - "phpVersions": [DEFAULT_PHP_VERSION], - "databases": ["mariadb:10.2"], - "esVersions": ["none"], - "federatedServerNeeded": False, - "filterTags": "", - "logLevel": "2", - "emailNeeded": False, - "ldapNeeded": False, - "cephS3": False, - "scalityS3": False, - "ssl": False, - "xForwardedFor": False, - "extraSetup": [], - "extraServices": [], - "extraTeardown": [], - "extraEnvironment": {}, - "extraCommandsBeforeTestRun": [], - "extraApps": {}, - "externalScality": [], - "useBundledApp": False, - "includeKeyInMatrixName": False, - "runAllSuites": False, - "runCoreTests": False, - "numberOfParts": 1, - "cron": "", - "pullRequestAndCron": "nightly", - "skip": False, - "debugSuites": [], - "skipExceptParts": [], - "enableApp": True, - "selUserNeeded": False, - } - - if "defaults" in config: - if "acceptance" in config["defaults"]: - for item in config["defaults"]["acceptance"]: - default[item] = config["defaults"]["acceptance"][item] - - for category, matrix in config["acceptance"].items(): - if type(matrix["suites"]) == "list": - suites = {} - for suite in matrix["suites"]: - suites[suite] = suite - else: - suites = matrix["suites"] - - if "debugSuites" in matrix and len(matrix["debugSuites"]) != 0: - if type(matrix["debugSuites"]) == "list": - suites = {} - for suite in matrix["debugSuites"]: - suites[suite] = suite - else: - suites = matrix["debugSuites"] - - for suite, alternateSuiteName in suites.items(): - isWebUI = suite.startswith("webUI") - isAPI = suite.startswith("api") - isCLI = suite.startswith("cli") - - params = {} - for item in default: - params[item] = matrix[item] if item in matrix else default[item] - - if params["skip"]: - continue - - if "externalScality" in params and len(params["externalScality"]) != 0: - # We want to use an external scality server for this pipeline. - # That uses some "standard" extraSetup and extraTeardown. - # Put the needed setup and teardown in place. - params["extraSetup"] = [ - { - "name": "configure-app", - "image": OC_CI_PHP % DEFAULT_PHP_VERSION, - "commands": [ - "cd %s/apps/files_primary_s3" % dir["server"], - "cp tests/drone/scality.config.php %s/config" % dir["server"], - "sed -i -e \"s/owncloud/owncloud-acceptance-tests-$DRONE_BUILD_NUMBER-$DRONE_STAGE_NUMBER/\" %s" % dir["scalityConfig"], - "sed -i -e \"s/accessKey1/$SCALITY_KEY/\" %s" % dir["scalityConfig"], - "sed -i -e \"s/verySecretKey1/$SCALITY_SECRET_ESCAPED/\" %s" % dir["scalityConfig"], - "sed -i -e \"s/http/https/\" %s" % dir["scalityConfig"], - "sed -i -e \"s/scality:8000/%s/\" %s" % (params["externalScality"]["externalServerUrl"], dir["scalityConfig"]), - "cd %s" % dir["server"], - "php occ s3:create-bucket owncloud-acceptance-tests-$DRONE_BUILD_NUMBER-$DRONE_STAGE_NUMBER --accept-warning", - "cd %s/apps/files_primary_s3" % dir["testrunner"], - ], - "environment": { - "SCALITY_KEY": { - "from_secret": params["externalScality"]["secrets"]["scality_key"], - }, - "SCALITY_SECRET": { - "from_secret": params["externalScality"]["secrets"]["scality_secret"], - }, - "SCALITY_SECRET_ESCAPED": { - "from_secret": params["externalScality"]["secrets"]["scality_secret_escaped"], - }, - }, - }, - ] - params["extraTeardown"] = [ - { - "name": "cleanup-scality-bucket", - "image": BANST_AWS_CLI, - "failure": "ignore", - "commands": [ - "aws configure set aws_access_key_id $SCALITY_KEY", - "aws configure set aws_secret_access_key $SCALITY_SECRET", - "aws --endpoint-url $SCALITY_ENDPOINT s3 rm --recursive s3://owncloud-acceptance-tests-$DRONE_BUILD_NUMBER-$DRONE_STAGE_NUMBER", - "%s/apps/files_primary_s3/tests/delete_all_object_versions.sh $SCALITY_ENDPOINT owncloud-acceptance-tests-$DRONE_BUILD_NUMBER-$DRONE_STAGE_NUMBER" % dir["testrunner"], - "aws --endpoint-url $SCALITY_ENDPOINT s3 rb --force s3://owncloud-acceptance-tests-$DRONE_BUILD_NUMBER-$DRONE_STAGE_NUMBER", - ], - "environment": { - "SCALITY_KEY": { - "from_secret": params["externalScality"]["secrets"]["scality_key"], - }, - "SCALITY_SECRET": { - "from_secret": params["externalScality"]["secrets"]["scality_secret"], - }, - "SCALITY_ENDPOINT": "https://%s" % params["externalScality"]["externalServerUrl"], - }, - "when": { - "status": [ - "failure", - "success", - ], - }, - }, - ] - - if isAPI or isCLI: - params["browsers"] = [""] - - cephS3Params = params["cephS3"] - if type(cephS3Params) == "bool": - cephS3Needed = cephS3Params - filesPrimaryS3NeededForCeph = cephS3Params - else: - cephS3Needed = True - filesPrimaryS3NeededForCeph = cephS3Params["filesPrimaryS3Needed"] if "filesPrimaryS3Needed" in cephS3Params else True - - scalityS3Params = params["scalityS3"] - if type(scalityS3Params) == "bool": - scalityS3Needed = scalityS3Params - filesPrimaryS3NeededForScality = scalityS3Params - else: - scalityS3Needed = True - filesPrimaryS3NeededForScality = scalityS3Params["filesPrimaryS3Needed"] if "filesPrimaryS3Needed" in scalityS3Params else True - - if ((ctx.repo.name != "files_primary_s3") and (filesPrimaryS3NeededForCeph or filesPrimaryS3NeededForScality)): - # If we are not already "files_primary_s3" and we need S3 object storage, then install the "files_primary_s3" app - extraAppsDict = { - "files_primary_s3": "composer install", - } - for app, command in params["extraApps"].items(): - extraAppsDict[app] = command - params["extraApps"] = extraAppsDict - - for testConfig in buildTestConfig(params): - debugPartsEnabled = (len(testConfig["skipExceptParts"]) != 0) - if debugPartsEnabled and testConfig["runPart"] not in testConfig["skipExceptParts"]: - continue - - name = "unknown" - phpVersionForDocker = testConfig["phpVersion"] - - # Get the first 3 characters of the PHP version (7.4 or 8.0 etc) - # And use that for constructing the pipeline name - # That helps shorten pipeline names when using owncloud-ci images - # that have longer names like 7.4-ubuntu20.04 - phpVersionForPipelineName = phpVersionForDocker[0:3] - if isWebUI or isAPI or isCLI: - esString = "-es" + testConfig["esVersion"] if testConfig["esVersion"] != "none" else "" - browserString = "" if testConfig["browser"] == "" else "-" + testConfig["browser"] - keyString = "-" + category if testConfig["includeKeyInMatrixName"] else "" - partString = "" if testConfig["numberOfParts"] == 1 else "-%d-%d" % (testConfig["numberOfParts"], testConfig["runPart"]) - name = "%s%s%s-%s%s-%s-php%s%s" % (alternateSuiteName, keyString, partString, testConfig["server"].replace("daily-", "").replace("-qa", ""), browserString, testConfig["database"].replace(":", ""), phpVersionForPipelineName, esString) - maxLength = 50 - nameLength = len(name) - if nameLength > maxLength: - print("Error: generated stage name of length", nameLength, "is not supported. The maximum length is " + str(maxLength) + ".", name) - errorFound = True - - environment = {} - for env in testConfig["extraEnvironment"]: - environment[env] = testConfig["extraEnvironment"][env] - - environment["TEST_SERVER_URL"] = "http://server" - environment["BEHAT_FILTER_TAGS"] = testConfig["filterTags"] - environment["DOWNLOADS_DIRECTORY"] = "%s/downloads" % dir["server"] - - if (testConfig["runAllSuites"] == False): - environment["BEHAT_SUITE"] = suite - else: - environment["DIVIDE_INTO_NUM_PARTS"] = testConfig["numberOfParts"] - environment["RUN_PART"] = testConfig["runPart"] - - if isWebUI: - environment["SELENIUM_HOST"] = "selenium" - environment["SELENIUM_PORT"] = "4444" - environment["BROWSER"] = testConfig["browser"] - environment["PLATFORM"] = "Linux" - if (testConfig["runCoreTests"]): - makeParameter = "test-acceptance-core-webui" - else: - makeParameter = "test-acceptance-webui" - - if isAPI: - if (testConfig["runCoreTests"]): - makeParameter = "test-acceptance-core-api" - else: - makeParameter = "test-acceptance-api" - - if isCLI: - if (testConfig["runCoreTests"]): - makeParameter = "test-acceptance-core-cli" - else: - makeParameter = "test-acceptance-cli" - - if testConfig["emailNeeded"]: - environment["EMAIL_HOST"] = "email" - - if testConfig["ldapNeeded"]: - environment["TEST_WITH_LDAP"] = True - - if (cephS3Needed or scalityS3Needed): - environment["OC_TEST_ON_OBJECTSTORE"] = "1" - if (testConfig["cephS3"] != False): - environment["S3_TYPE"] = "ceph" - if (testConfig["scalityS3"] != False): - environment["S3_TYPE"] = "scality" - federationDbSuffix = "-federated" - - result = { - "kind": "pipeline", - "type": "docker", - "name": name, - "workspace": { - "base": dir["base"], - "path": "testrunner/apps/%s" % ctx.repo.name, - }, - "steps": skipIfUnchanged(ctx, "acceptance-tests") + - installCore(ctx, testConfig["server"], testConfig["database"], testConfig["useBundledApp"]) + - installTestrunner(ctx, DEFAULT_PHP_VERSION, testConfig["useBundledApp"]) + - (installFederated(testConfig["server"], phpVersionForDocker, testConfig["logLevel"], testConfig["database"], federationDbSuffix) + owncloudLog("federated") if testConfig["federatedServerNeeded"] else []) + - installAppPhp(ctx, phpVersionForDocker) + - installAppJavaScript(ctx) + - installExtraApps(phpVersionForDocker, testConfig["extraApps"]) + - setupServerAndApp(ctx, phpVersionForDocker, testConfig["logLevel"], testConfig["federatedServerNeeded"], params["enableApp"]) + - owncloudLog("server") + - setupCeph(testConfig["cephS3"]) + - setupScality(testConfig["scalityS3"]) + - setupElasticSearch(testConfig["esVersion"]) + - testConfig["extraSetup"] + - waitForServer(testConfig["federatedServerNeeded"]) + - waitForEmailService(testConfig["emailNeeded"]) + - fixPermissions(phpVersionForDocker, testConfig["federatedServerNeeded"], params["selUserNeeded"]) + - waitForBrowserService(testConfig["browser"]) + - [ - ({ - "name": "acceptance-tests", - "image": OC_CI_PHP % DEFAULT_PHP_VERSION, - "environment": environment, - "commands": testConfig["extraCommandsBeforeTestRun"] + [ - "touch %s/saved-settings.sh" % dir["base"], - ". %s/saved-settings.sh" % dir["base"], - "make %s" % makeParameter, - ], - "volumes": [{ - "name": "downloads", - "path": "%s/downloads" % dir["server"], - }], - }), - ] + testConfig["extraTeardown"], - "services": databaseService(testConfig["database"]) + - browserService(testConfig["browser"]) + - emailService(testConfig["emailNeeded"]) + - ldapService(testConfig["ldapNeeded"]) + - cephService(testConfig["cephS3"]) + - scalityService(testConfig["scalityS3"]) + - elasticSearchService(testConfig["esVersion"]) + - testConfig["extraServices"] + - owncloudService(testConfig["server"], phpVersionForDocker, "server", dir["server"], testConfig["ssl"], testConfig["xForwardedFor"]) + - (( - owncloudService(testConfig["server"], phpVersionForDocker, "federated", dir["federated"], testConfig["ssl"], testConfig["xForwardedFor"]) + - databaseServiceForFederation(testConfig["database"], federationDbSuffix) - ) if testConfig["federatedServerNeeded"] else []), - "depends_on": [], - "trigger": {}, - "volumes": [{ - "name": "downloads", - "temp": {}, - }], - } - - if (testConfig["cron"] != ""): - result["trigger"]["cron"] = testConfig["cron"] - elif ((testConfig["pullRequestAndCron"] != "") and (ctx.build.event != "pull_request")): - result["trigger"]["cron"] = testConfig["pullRequestAndCron"] - else: - result["trigger"]["ref"] = [ - "refs/pull/**", - "refs/tags/**", - ] - - pipelines.append(result) - - if errorFound: - return False - - return pipelines - -def sonarAnalysis(ctx, phpVersion = DEFAULT_PHP_VERSION): - sonar_env = { - "SONAR_TOKEN": { - "from_secret": "sonar_token", - }, - "SONAR_SCANNER_OPTS": "-Xdebug", - } - - if ctx.build.event == "pull_request": - sonar_env.update({ - "SONAR_PULL_REQUEST_BASE": "%s" % (ctx.build.target), - "SONAR_PULL_REQUEST_BRANCH": "%s" % (ctx.build.source), - "SONAR_PULL_REQUEST_KEY": "%s" % (ctx.build.ref.replace("refs/pull/", "").split("/")[0]), - }) - - repo_slug = ctx.build.source_repo if ctx.build.source_repo else ctx.repo.slug - - result = { - "kind": "pipeline", - "type": "docker", - "name": "sonar-analysis", - "workspace": { - "base": dir["base"], - "path": "server/apps/%s" % ctx.repo.name, - }, - "clone": { - "disable": True, # Sonarcloud does not apply issues on already merged branch - }, - "steps": [ - { - "name": "clone", - "image": OC_CI_ALPINE, - "commands": [ - "git clone https://github.com/%s.git ." % repo_slug, - "git checkout $DRONE_COMMIT", - ], - }, - ] + - skipIfUnchanged(ctx, "unit-tests") + - cacheRestore() + - composerInstall(phpVersion) + - installCore(ctx, "daily-master-qa", "sqlite", False) + - [ - { - "name": "sync-from-cache", - "image": MINIO_MC, - "environment": MINIO_MC_ENV, - "commands": [ - "mkdir -p results", - "mc alias set cache $MC_HOST $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY", - "mc mirror cache/cache/%s/%s results/" % (ctx.repo.slug, ctx.build.commit + "-${DRONE_BUILD_NUMBER}"), - ], - }, - { - "name": "list-coverage-results", - "image": OC_CI_PHP % phpVersion, - "commands": [ - "ls -l results", - ], - }, - { - "name": "sonarcloud", - "image": SONARSOURCE_SONAR_SCANNER_CLI, - "environment": sonar_env, - "when": { - "instance": [ - "drone.owncloud.services", - "drone.owncloud.com", - ], - }, - }, - { - "name": "purge-cache", - "image": MINIO_MC, - "environment": MINIO_MC_ENV, - "commands": [ - "mc alias set cache $MC_HOST $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY", - "mc rm --recursive --force cache/cache/%s/%s" % (ctx.repo.slug, ctx.build.commit + "-${DRONE_BUILD_NUMBER}"), - ], - }, - ], - "depends_on": [], - "trigger": { - "ref": [ - "refs/heads/master", - "refs/pull/**", - "refs/tags/**", - ], - }, - } - - for branch in config["branches"]: - result["trigger"]["ref"].append("refs/heads/%s" % branch) - - return result - -def databaseService(db): - dbName = getDbName(db) - if (dbName == "mariadb") or (dbName == "mysql"): - service = { - "name": dbName, - "image": db, - "environment": { - "MYSQL_USER": getDbUsername(db), - "MYSQL_PASSWORD": getDbPassword(db), - "MYSQL_DATABASE": getDbDatabase(db), - "MYSQL_ROOT_PASSWORD": getDbRootPassword(), - }, - } - if (db == "mysql:8.0"): - service["command"] = ["--default-authentication-plugin=mysql_native_password"] - return [service] - - if dbName == "postgres": - return [{ - "name": dbName, - "image": db, - "environment": { - "POSTGRES_USER": getDbUsername(db), - "POSTGRES_PASSWORD": getDbPassword(db), - "POSTGRES_DB": getDbDatabase(db), - }, - }] - - if dbName == "oracle": - return [{ - "name": dbName, - "image": OC_CI_ORACLE_XE, - "environment": { - "ORACLE_USER": getDbUsername(db), - "ORACLE_PASSWORD": getDbPassword(db), - "ORACLE_DB": getDbDatabase(db), - "ORACLE_DISABLE_ASYNCH_IO": "true", - }, - }] - - return [] - -def browserService(browser): - if browser == "chrome": - return [{ - "name": "selenium", - "image": SELENIUM_STANDALONE_CHROME_DEBUG, - "environment": { - "JAVA_OPTS": "-Dselenium.LOGGER.level=WARNING", - }, - "volumes": [{ - "name": "downloads", - "path": dir["browserService"], - }], - }] - - if browser == "firefox": - return [{ - "name": "selenium", - "image": SELENIUM_STANDALONE_FIREFOX_DEBUG, - "environment": { - "JAVA_OPTS": "-Dselenium.LOGGER.level=WARNING", - "SE_OPTS": "-enablePassThrough false", - }, - "volumes": [{ - "name": "downloads", - "path": dir["browserService"], - }], - }] - - return [] - -def waitForBrowserService(browser): - if browser in ["chrome", "firefox"]: - return [{ - "name": "wait-for-selenium", - "image": OC_CI_WAIT_FOR, - "commands": [ - "wait-for -it selenium:4444 -t 600", - ], - }] - - return [] - -def emailService(emailNeeded): - if emailNeeded: - return [{ - "name": "email", - "image": INBUCKET_INBUCKET, - }] - - return [] - -def waitForEmailService(emailNeeded): - if emailNeeded: - return [{ - "name": "wait-for-email", - "image": OC_CI_WAIT_FOR, - "commands": [ - "wait-for -it email:9000 -t 600", - ], - }] - - return [] - -def ldapService(ldapNeeded): - if ldapNeeded: - return [{ - "name": "ldap", - "image": OSIXIA_OPEN_LDAP, - "environment": { - "LDAP_DOMAIN": "owncloud.com", - "LDAP_ORGANISATION": "owncloud", - "LDAP_ADMIN_PASSWORD": "admin", - "LDAP_TLS_VERIFY_CLIENT": "never", - }, - }] - - return [] - -def elasticSearchService(esVersion): - if esVersion == "none": - return [] - - return [{ - "name": "elasticsearch", - "image": OC_OPS_ELASTIC_SEARCH % esVersion, - "environment": { - "ELASTICSEARCH_ROOT_LOG_LEVEL": "warn", - "ELASTICSEARCH_BOOTSTRAP_MEMORY_LOCK": "false", - }, - }] - -def scalityService(serviceParams): - serviceEnvironment = { - "HOST_NAME": "scality", - } - - if type(serviceParams) == "bool": - if not serviceParams: - return [] - elif "extraEnvironment" in serviceParams: - for env in serviceParams["extraEnvironment"]: - serviceEnvironment[env] = serviceParams["extraEnvironment"][env] - - return [{ - "name": "scality", - "image": OC_CI_SCALITY_S3_SERVER, - "environment": serviceEnvironment, - }] - -def cephService(serviceParams): - serviceEnvironment = { - "NETWORK_AUTO_DETECT": "4", - "RGW_NAME": "ceph", - "CEPH_DEMO_UID": "owncloud", - "CEPH_DEMO_ACCESS_KEY": "owncloud123456", - "CEPH_DEMO_SECRET_KEY": "secret123456", - } - - if type(serviceParams) == "bool": - if not serviceParams: - return [] - elif "extraEnvironment" in serviceParams: - for env in serviceParams["extraEnvironment"]: - serviceEnvironment[env] = serviceParams["extraEnvironment"][env] - - return [{ - "name": "ceph", - "image": OC_CI_CEPH, - "environment": serviceEnvironment, - }] - -def owncloudService(version, phpVersion, name, path, ssl, xForwardedFor): - if ssl: - environment = { - "APACHE_WEBROOT": path, - "APACHE_CONFIG_TEMPLATE": "ssl", - "APACHE_SSL_CERT_CN": "server", - "APACHE_SSL_CERT": "%s/%s.crt" % (dir["base"], name), - "APACHE_SSL_KEY": "%s/%s.key" % (dir["base"], name), - "APACHE_LOGGING_PATH": "/dev/null", - } - else: - environment = { - "APACHE_WEBROOT": path, - "APACHE_LOGGING_PATH": "/dev/null", - } - - return [{ - "name": name, - "image": OC_CI_PHP % phpVersion, - "environment": environment, - "commands": ([ - "a2enmod remoteip", - "cd /etc/apache2", - "echo 'RemoteIPHeader X-Forwarded-For' >> apache2.conf", - # This replaces the first occurrence of "%h with "%a in apache2.conf file telling Apache to log the client - # IP as recorded by mod_remoteip (%a) rather than hostname (%h). For more info check this out: - # https://www.digitalocean.com/community/questions/get-client-public-ip-on-apache-server-used-behind-load-balancer - "sed -i '0,/\"%h/s//\"%a/' apache2.conf", - ] if xForwardedFor else []) + [ - "/usr/local/bin/apachectl -e debug -D FOREGROUND", - ], - }] - -def getDbName(db): - return db.split(":")[0] - -def getDbUsername(db): - name = getDbName(db) - - # The Oracle image has the Db Username hardcoded - if name == "oracle": - return "autotest" - - return "owncloud" - -def getDbPassword(db): - name = getDbName(db) - - # The Oracle image has the Db Password hardcoded - if name == "oracle": - return "owncloud" - - return "owncloud" - -def getDbRootPassword(): - return "owncloud" - -def getDbDatabase(db): - name = getDbName(db) - - # The Oracle image has the Db Name hardcoded - if name == "oracle": - return "XE" - - return "owncloud" - -def getNodeJsVersion(): - if "nodeJsVersion" not in config: - # We use nodejs 14 as the default - return DEFAULT_NODEJS_VERSION - else: - return config["nodeJsVersion"] - -def cacheRestore(): - return [{ - "name": "cache-restore", - "image": PLUGINS_S3_CACHE, - "settings": { - "access_key": { - "from_secret": "cache_s3_access_key", - }, - "endpoint": { - "from_secret": "cache_s3_server", - }, - "restore": True, - "secret_key": { - "from_secret": "cache_s3_secret_key", - }, - }, - "when": { - "instance": [ - "drone.owncloud.services", - "drone.owncloud.com", - ], - }, - }] - -def composerInstall(phpVersion): - return [{ - "name": "composer-install", - "image": OC_CI_PHP % phpVersion, - "environment": { - "COMPOSER_HOME": "/drone/src/.cache/composer", - }, - "commands": [ - "make vendor", - ], - }] - -def installCore(ctx, version, db, useBundledApp): - host = getDbName(db) - dbType = host - - username = getDbUsername(db) - password = getDbPassword(db) - database = getDbDatabase(db) - - if host == "mariadb": - dbType = "mysql" - - if host == "postgres": - dbType = "pgsql" - - if host == "oracle": - dbType = "oci" - - stepDefinition = { - "name": "install-core", - "image": OC_CI_CORE, - "settings": { - "version": version, - "core_path": dir["server"], - "db_type": dbType, - "db_name": database, - "db_host": host, - "db_username": username, - "db_password": password, - }, - } - - if not useBundledApp: - stepDefinition["settings"]["exclude"] = "apps/%s" % ctx.repo.name - - return [stepDefinition] - -def installTestrunner(ctx, phpVersion, useBundledApp): - return [{ - "name": "install-testrunner", - "image": OC_CI_PHP % phpVersion, - "commands": [ - "mkdir /tmp/testrunner", - "git clone -b master --depth=1 https://github.com/owncloud/core.git /tmp/testrunner", - "rsync -aIX /tmp/testrunner %s" % dir["base"], - ] + ([ - "cp -r %s/apps/%s %s/apps/" % (dir["testrunner"], ctx.repo.name, dir["server"]), - ] if not useBundledApp else []), - }] - -def installExtraApps(phpVersion, extraApps): - commandArray = [] - for app, command in extraApps.items(): - commandArray.append("ls %s/apps/%s || git clone https://github.com/owncloud/%s.git %s/apps/%s" % (dir["testrunner"], app, app, dir["testrunner"], app)) - commandArray.append("ls %s/apps/%s || cp -r %s/apps/%s %s/apps/" % (dir["server"], app, dir["testrunner"], app, dir["server"])) - if (command != ""): - commandArray.append("cd %s/apps/%s" % (dir["server"], app)) - commandArray.append(command) - commandArray.append("cd %s" % dir["server"]) - commandArray.append("php occ a:l") - commandArray.append("php occ a:e %s" % app) - commandArray.append("php occ a:l") - - if (commandArray == []): - return [] - - return [{ - "name": "install-extra-apps", - "image": OC_CI_PHP % phpVersion, - "commands": commandArray, - }] - -def installAppPhp(ctx, phpVersion): - if "appInstallCommandPhp" not in config: - return [] - - # config["appInstallCommandPhp"] must be the command that is needed to - # install just the PHP-related part of the app. The docker image has PHP - # and "base" tools. But it does not have JavaScript tools like nodejs, - # npm, yarn etc. - return [ - { - "name": "install-app-php-%s" % ctx.repo.name, - "image": OC_CI_PHP % phpVersion, - "commands": [ - "cd %s/apps/%s" % (dir["server"], ctx.repo.name), - config["appInstallCommandPhp"], - ], - }, - ] - -def installAppJavaScript(ctx): - nothingToDo = True - commandArray = [ - "cd %s/apps/%s" % (dir["server"], ctx.repo.name), - ] - - if "appInstallCommandJavaScript" in config: - nothingToDo = False - commandArray.append(config["appInstallCommandJavaScript"]) - - if "buildJsDeps" in config: - if config["buildJsDeps"]: - nothingToDo = False - commandArray.append("make install-js-deps") - commandArray.append("make build-dev") - - if (nothingToDo): - return [] - - return [ - { - "name": "install-app-js-%s" % ctx.repo.name, - "image": OC_CI_NODEJS % getNodeJsVersion(), - "commands": commandArray, - }, - ] - -def setupServerAndApp(ctx, phpVersion, logLevel, federatedServerNeeded = False, enableApp = True): - return [{ - "name": "setup-server-%s" % ctx.repo.name, - "image": OC_CI_PHP % phpVersion, - "commands": [ - "cd %s" % dir["server"], - "php occ a:l", - "php occ a:e %s" % ctx.repo.name if enableApp else "", - "php occ a:e testing", - "php occ a:l", - "php occ config:system:set trusted_domains 1 --value=server", - "php occ log:manage --level %s" % logLevel, - "php occ config:system:set csrf.disabled --value=true" if federatedServerNeeded else "", - ], - }] - -def setupCeph(serviceParams): - if type(serviceParams) == "bool": - if serviceParams: - # specify an empty dict that will get the defaults - serviceParams = {} - else: - return [] - - createFirstBucket = serviceParams["createFirstBucket"] if "createFirstBucket" in serviceParams else True - setupCommands = serviceParams["setupCommands"] if "setupCommands" in serviceParams else [ - "cd %s/apps/files_primary_s3" % dir["server"], - "cp tests/drone/ceph.config.php %s/config" % dir["server"], - "cd %s" % dir["server"], - ] - - return [ - { - "name": "wait-for-ceph", - "image": OC_CI_WAIT_FOR, - "commands": [ - "wait-for -it ceph:80 -t 600", - ], - }, - { - "name": "setup-ceph", - "image": OC_CI_PHP % DEFAULT_PHP_VERSION, - "commands": setupCommands + ([ - "./apps/files_primary_s3/tests/drone/create-bucket.sh", - ] if createFirstBucket else []), - }, - ] - -def setupScality(serviceParams): - if type(serviceParams) == "bool": - if serviceParams: - # specify an empty dict that will get the defaults - serviceParams = {} - else: - return [] - - specialConfig = "." + serviceParams["config"] if "config" in serviceParams else "" - configFile = "scality%s.config.php" % specialConfig - createFirstBucket = serviceParams["createFirstBucket"] if "createFirstBucket" in serviceParams else True - createExtraBuckets = serviceParams["createExtraBuckets"] if "createExtraBuckets" in serviceParams else False - setupCommands = serviceParams["setupCommands"] if "setupCommands" in serviceParams else [ - "cd %s/apps/files_primary_s3" % dir["server"], - "cp tests/drone/%s %s/config" % (configFile, dir["server"]), - "cd %s" % dir["server"], - ] - - return [ - { - "name": "wait-for-scality", - "image": OC_CI_WAIT_FOR, - "commands": [ - "wait-for -it scality:8000 -t 600", - ], - }, - { - "name": "setup-scality", - "image": OC_CI_PHP % DEFAULT_PHP_VERSION, - "commands": setupCommands + ([ - "php occ s3:create-bucket owncloud --accept-warning", - ] if createFirstBucket else []) + ([ - "for I in $(seq 1 9); do php ./occ s3:create-bucket owncloud$I --accept-warning; done", - ] if createExtraBuckets else []), - }, - ] - -def setupElasticSearch(esVersion): - if esVersion == "none": - return [] - - return [ - { - "name": "wait-for-es", - "image": OC_CI_WAIT_FOR, - "commands": [ - "wait-for -it elasticsearch:9200 -t 600", - ], - }, - { - "name": "setup-es", - "image": OC_CI_PHP % DEFAULT_PHP_VERSION, - "commands": [ - "cd %s" % dir["server"], - "php occ config:app:set search_elastic servers --value elasticsearch", - "php occ search:index:reset --force", - ], - }, - ] - -def waitForServer(federatedServerNeeded): - return [{ - "name": "wait-for-server", - "image": OC_CI_WAIT_FOR, - "commands": [ - "wait-for -it server:80 -t 600", - ] + ([ - "wait-for -it federated:80 -t 600", - ] if federatedServerNeeded else []), - }] - -def fixPermissions(phpVersion, federatedServerNeeded, selUserNeeded = False): - return [{ - "name": "fix-permissions", - "image": OC_CI_PHP % phpVersion, - "commands": [ - "chown -R www-data %s" % dir["server"], - ] + ([ - "chown -R www-data %s" % dir["federated"], - ] if federatedServerNeeded else []) + ([ - "chmod 777 %s" % dir["browserService"], - ] if selUserNeeded else []), - "volumes": [{ - "name": "downloads", - "path": dir["browserService"], - }], - }] - -def owncloudLog(server): - return [{ - "name": "owncloud-log-%s" % server, - "image": OC_UBUNTU, - "detach": True, - "commands": [ - "tail -f %s/%s/data/owncloud.log" % (dir["base"], server), - ], - }] - -def dependsOn(earlierStages, nextStages): - for earlierStage in earlierStages: - for nextStage in nextStages: - nextStage["depends_on"].append(earlierStage["name"]) - -def installFederated(federatedServerVersion, phpVersion, logLevel, db, dbSuffix = "-federated"): - host = getDbName(db) - dbType = host - - username = getDbUsername(db) - password = getDbPassword(db) - database = getDbDatabase(db) + dbSuffix - - if host == "mariadb": - dbType = "mysql" - elif host == "postgres": - dbType = "pgsql" - elif host == "oracle": - dbType = "oci" - return [ - { - "name": "install-federated", - "image": OC_CI_CORE, - "settings": { - "version": federatedServerVersion, - "core_path": dir["federated"], - "db_type": "mysql", - "db_name": database, - "db_host": host + dbSuffix, - "db_username": username, - "db_password": password, - }, - }, - { - "name": "configure-federation", - "image": OC_CI_PHP % phpVersion, - "commands": [ - "echo 'export TEST_SERVER_FED_URL=http://federated' > %s/saved-settings.sh" % dir["base"], - "cd %s" % dir["federated"], - "php occ a:l", - "php occ a:e files_external", - "php occ a:e testing", - "php occ a:l", - "php occ config:system:set trusted_domains 1 --value=federated", - "php occ log:manage --level %s" % logLevel, - "php occ config:list", - ], - }, - ] - -def databaseServiceForFederation(db, suffix): - dbName = getDbName(db) - - if dbName not in ["mariadb", "mysql"]: - print("Not implemented federated database for ", dbName) - return [] - - service = { - "name": dbName + suffix, - "image": db, - "environment": { - "MYSQL_USER": getDbUsername(db), - "MYSQL_PASSWORD": getDbPassword(db), - "MYSQL_DATABASE": getDbDatabase(db) + suffix, - "MYSQL_ROOT_PASSWORD": getDbRootPassword(), - }, - } - if (db == "mysql:8.0"): - service["command"] = ["--default-authentication-plugin=mysql_native_password"] - return [service] - -def buildTestConfig(params): - configs = [] - for server in params["servers"]: - for browser in params["browsers"]: - for phpVersion in params["phpVersions"]: - for db in params["databases"]: - for esVersion in params["esVersions"]: - for runPart in range(1, params["numberOfParts"] + 1): - config = dict(params) - config["server"] = server - config["browser"] = browser - config["phpVersion"] = phpVersion - config["database"] = db - config["esVersion"] = esVersion - config["runPart"] = runPart - configs.append(config) - return configs - -def checkStarlark(): - return [{ - "kind": "pipeline", - "type": "docker", - "name": "check-starlark", - "steps": [ - { - "name": "format-check-starlark", - "image": OC_CI_BAZEL_BUILDIFIER, - "commands": [ - "buildifier --mode=check .drone.star", - ], - }, - { - "name": "show-diff", - "image": OC_CI_BAZEL_BUILDIFIER, - "commands": [ - "buildifier --mode=fix .drone.star", - "git diff", - ], - "when": { - "status": [ - "failure", - ], - }, - }, - ], - "depends_on": [], - "trigger": { - "ref": [ - "refs/pull/**", - ], - }, - }] - -def phplint(ctx): - pipelines = [] - - if "phplint" not in config: - return pipelines - - if type(config["phplint"]) == "bool": - if not config["phplint"]: - return pipelines - - result = { - "kind": "pipeline", - "type": "docker", - "name": "lint-test", - "workspace": { - "base": dir["base"], - "path": "server/apps/%s" % ctx.repo.name, - }, - "steps": skipIfUnchanged(ctx, "lint") + - installNPM() + - lintTest(), - "depends_on": [], - "trigger": { - "ref": [ - "refs/heads/master", - "refs/tags/**", - "refs/pull/**", - ], - }, - } - - for branch in config["branches"]: - result["trigger"]["ref"].append("refs/heads/%s" % branch) - - pipelines.append(result) - - return pipelines - -def installNPM(): - return [{ - "name": "npm-install", - "image": OC_CI_NODEJS % getNodeJsVersion(), - "commands": [ - "yarn install --frozen-lockfile", - ], - }] - -def lintTest(): - return [{ - "name": "lint-test", - "image": OC_CI_PHP % DEFAULT_PHP_VERSION, - "commands": [ - "make test-lint", - ], - }] - -def skipIfUnchanged(ctx, type): - if ("full-ci" in ctx.build.title.lower()): - return [] - - skip_step = { - "name": "skip-if-unchanged", - "image": OC_CI_DRONE_SKIP_PIPELINE, - "when": { - "event": [ - "pull_request", - ], - }, - } - - # these files are not relevant for test pipelines - # if only files in this array are changed, then don't even run the "lint" - # pipelines (like code-style, phan, phpstan...) - allow_skip_if_changed = [ - "^.github/.*", - "^changelog/.*", - "^docs/.*", - "CHANGELOG.md", - "CONTRIBUTING.md", - "LICENSE", - "LICENSE.md", - "README.md", - ] - - if type == "lint": - skip_step["settings"] = { - "ALLOW_SKIP_CHANGED": allow_skip_if_changed, - } - return [skip_step] - - if type == "acceptance-tests": - # if any of these files are touched then run all acceptance tests - # note: some oC10 apps have various directories like handlers, rules, etc. - # so those are all listed here so that this starlark code can be - # the same for every oC10 app. - acceptance_files = [ - "^tests/acceptance/.*", - "^tests/drone/.*", - "^tests/TestHelpers/.*", - "^vendor-bin/behat/.*", - "^appinfo/.*", - "^command/.*", - "^controller/.*", - "^css/.*", - "^db/.*", - "^handlers/.*", - "^js/.*", - "^lib/.*", - "^rules/.*", - "^src/.*", - "^templates/.*", - "composer.json", - "composer.lock", - "Makefile", - "package.json", - "package-lock.json", - "yarn.lock", - ] - skip_step["settings"] = { - "DISALLOW_SKIP_CHANGED": acceptance_files, - } - return [skip_step] - - if type == "unit-tests": - # if any of these files are touched then run all unit tests - # note: some oC10 apps have various directories like handlers, rules, etc. - # so those are all listed here so that this starlark code can be - # the same for every oC10 app. - unit_files = [ - "^tests/integration/.*", - "^tests/js/.*", - "^tests/Unit/.*", - "^tests/unit/.*", - "^appinfo/.*", - "^command/.*", - "^controller/.*", - "^css/.*", - "^db/.*", - "^handlers/.*", - "^js/.*", - "^lib/.*", - "^rules/.*", - "^src/.*", - "^templates/.*", - "composer.json", - "composer.lock", - "Makefile", - "package.json", - "package-lock.json", - "phpunit.xml", - "yarn.lock", - "sonar-project.properties", - ] - skip_step["settings"] = { - "DISALLOW_SKIP_CHANGED": unit_files, - } - return [skip_step] - - return [] diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000000..ea9344aa7a --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,56 @@ +name: CI + +on: + push: + branches: + - master + pull_request: + types: + - opened + - synchronize + - reopened + +permissions: + contents: read + +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +env: + APP_NAME: gallery + PHP_VERSIONS: '["8.3"]' + +jobs: + get-vars: + runs-on: ubuntu-latest + outputs: + app-name: ${{ env.APP_NAME }} + php-versions: ${{ env.PHP_VERSIONS }} + steps: + - name: Set variables + run: | + echo "App name $APP_NAME" + echo "PHP versions string: $PHP_VERSIONS" + + semantic-git-messages: + name: Commits + uses: owncloud/reusable-workflows/.github/workflows/semantic-git-message.yml@main + + php-code-style: + name: PHP Code Style + needs: + - get-vars + uses: owncloud/reusable-workflows/.github/workflows/php-codestyle.yml@main + with: + app-name: ${{ needs.get-vars.outputs.app-name }} + php-versions: ${{ needs.get-vars.outputs.php-versions }} + + php-unit: + name: PHP Unit + needs: + - get-vars + uses: owncloud/reusable-workflows/.github/workflows/php-unit.yml@main + with: + app-name: ${{ needs.get-vars.outputs.app-name }} + php-versions: ${{ needs.get-vars.outputs.php-versions }} diff --git a/appinfo/app.php b/appinfo/app.php index cf626372c8..45b2d38bd4 100644 --- a/appinfo/app.php +++ b/appinfo/app.php @@ -26,29 +26,29 @@ $c->query('OCP\INavigationManager') ->add( function () use ($c, $appName) { - $urlGenerator = $c->query('OCP\IURLGenerator'); - $l10n = $c->query('OCP\IL10N'); + $urlGenerator = $c->query('OCP\IURLGenerator'); + $l10n = $c->query('OCP\IL10N'); - return [ - 'id' => $appName, + return [ + 'id' => $appName, - // Sorting weight for the navigation. The higher the number, the higher - // will it be listed in the navigation - 'order' => 2, + // Sorting weight for the navigation. The higher the number, the higher + // will it be listed in the navigation + 'order' => 2, - // The route that will be shown on startup when called from within the GUI - // Public links are using another route, see appinfo/routes.php - 'href' => $urlGenerator->linkToRoute($appName . '.page.index'), + // The route that will be shown on startup when called from within the GUI + // Public links are using another route, see appinfo/routes.php + 'href' => $urlGenerator->linkToRoute($appName . '.page.index'), - // The icon that will be shown in the navigation - // This file needs to exist in img/ - 'icon' => $urlGenerator->imagePath($appName, 'app.svg'), + // The icon that will be shown in the navigation + // This file needs to exist in img/ + 'icon' => $urlGenerator->imagePath($appName, 'app.svg'), - // The title of the application. This will be used in the - // navigation or on the settings page - 'name' => $l10n->t('Gallery') - ]; - } + // The title of the application. This will be used in the + // navigation or on the settings page + 'name' => $l10n->t('Gallery') + ]; + } ); /** diff --git a/appinfo/info.xml b/appinfo/info.xml index 20de67d2e7..d46cef7223 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -33,7 +33,8 @@ Media gallery that adds image viewing capabilities to files view and public link https://github.com/owncloud/gallery/issues https://github.com/owncloud/gallery.git - + + diff --git a/composer.json b/composer.json index f4acf657dd..d3cfec6176 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ ], "config" : { "platform": { - "php": "7.3" + "php": "8.3" }, "allow-plugins": { "bamarni/composer-bin-plugin": true, diff --git a/composer.lock b/composer.lock index 9f19a70a34..35b7c076e8 100644 --- a/composer.lock +++ b/composer.lock @@ -4,24 +4,24 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "55acd4110624022f8f1868a9bd637b95", + "content-hash": "059235fceb42cf8bc52fd04749bf5c57", "packages": [ { "name": "symfony/polyfill-ctype", - "version": "v1.26.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4" + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", - "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-ctype": "*" @@ -31,12 +31,9 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -70,7 +67,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" }, "funding": [ { @@ -81,12 +78,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2022-05-24T11:49:31+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/yaml", @@ -145,16 +146,16 @@ "packages-dev": [ { "name": "bamarni/composer-bin-plugin", - "version": "1.7.0", + "version": "1.9.1", "source": { "type": "git", "url": "https://github.com/bamarni/composer-bin-plugin.git", - "reference": "c1bbee3662a2a84c6aad84b7c6daefcae29e5690" + "reference": "641d0663f5ac270b1aeec4337b7856f76204df47" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bamarni/composer-bin-plugin/zipball/c1bbee3662a2a84c6aad84b7c6daefcae29e5690", - "reference": "c1bbee3662a2a84c6aad84b7c6daefcae29e5690", + "url": "https://api.github.com/repos/bamarni/composer-bin-plugin/zipball/641d0663f5ac270b1aeec4337b7856f76204df47", + "reference": "641d0663f5ac270b1aeec4337b7856f76204df47", "shasum": "" }, "require": { @@ -162,19 +163,19 @@ "php": "^7.2.5 || ^8.0" }, "require-dev": { - "composer/composer": "^2.0", + "composer/composer": "^2.2.26", "ext-json": "*", "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.1", - "phpunit/phpunit": "^8.5 || ^9.5", - "symfony/console": "^5.4.7 || ^6.0.7", - "symfony/finder": "^5.4.7 || ^6.0.7", - "symfony/process": "^5.4.7 || ^6.0.7" + "phpstan/phpstan": "^1.8 || ^2.0", + "phpstan/phpstan-phpunit": "^1.1 || ^2.0", + "phpunit/phpunit": "^8.5 || ^9.6 || ^10.0", + "symfony/console": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0", + "symfony/finder": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0", + "symfony/process": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0" }, "type": "composer-plugin", "extra": { - "class": "Bamarni\\Composer\\Bin\\Plugin" + "class": "Bamarni\\Composer\\Bin\\BamarniBinPlugin" }, "autoload": { "psr-4": { @@ -196,31 +197,37 @@ ], "support": { "issues": "https://github.com/bamarni/composer-bin-plugin/issues", - "source": "https://github.com/bamarni/composer-bin-plugin/tree/1.7.0" + "source": "https://github.com/bamarni/composer-bin-plugin/tree/1.9.1" }, - "time": "2022-07-10T17:28:16+00:00" + "time": "2026-02-04T10:18:12+00:00" }, { "name": "behat/gherkin", - "version": "v4.9.0", + "version": "v4.16.1", "source": { "type": "git", "url": "https://github.com/Behat/Gherkin.git", - "reference": "0bc8d1e30e96183e4f36db9dc79caead300beff4" + "reference": "e26037937dfd48528746764dd870bc5d0836665f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Behat/Gherkin/zipball/0bc8d1e30e96183e4f36db9dc79caead300beff4", - "reference": "0bc8d1e30e96183e4f36db9dc79caead300beff4", + "url": "https://api.github.com/repos/Behat/Gherkin/zipball/e26037937dfd48528746764dd870bc5d0836665f", + "reference": "e26037937dfd48528746764dd870bc5d0836665f", "shasum": "" }, "require": { - "php": "~7.2|~8.0" + "composer-runtime-api": "^2.2", + "php": ">=8.1 <8.6" }, "require-dev": { - "cucumber/cucumber": "dev-gherkin-22.0.0", - "phpunit/phpunit": "~8|~9", - "symfony/yaml": "~3|~4|~5" + "cucumber/gherkin-monorepo": "dev-gherkin-v37.0.0", + "friendsofphp/php-cs-fixer": "^3.77", + "mikey179/vfsstream": "^1.6", + "phpstan/extension-installer": "^1", + "phpstan/phpstan": "^2", + "phpstan/phpstan-phpunit": "^2", + "phpunit/phpunit": "^10.5", + "symfony/yaml": "^5.4 || ^6.4 || ^7.0" }, "suggest": { "symfony/yaml": "If you want to parse features, represented in YAML files" @@ -232,8 +239,8 @@ } }, "autoload": { - "psr-0": { - "Behat\\Gherkin": "src/" + "psr-4": { + "Behat\\Gherkin\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -244,11 +251,11 @@ { "name": "Konstantin Kudryashov", "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "homepage": "https://everzet.com" } ], "description": "Gherkin DSL parser for PHP", - "homepage": "http://behat.org/", + "homepage": "https://behat.org/", "keywords": [ "BDD", "Behat", @@ -259,27 +266,41 @@ ], "support": { "issues": "https://github.com/Behat/Gherkin/issues", - "source": "https://github.com/Behat/Gherkin/tree/v4.9.0" + "source": "https://github.com/Behat/Gherkin/tree/v4.16.1" }, - "time": "2021-10-12T13:05:09+00:00" + "funding": [ + { + "url": "https://github.com/acoulton", + "type": "github" + }, + { + "url": "https://github.com/carlos-granados", + "type": "github" + }, + { + "url": "https://github.com/stof", + "type": "github" + } + ], + "time": "2025-12-08T16:12:58+00:00" }, { "name": "codeception/c3", - "version": "2.6.5", + "version": "2.9.0", "source": { "type": "git", "url": "https://github.com/Codeception/c3.git", - "reference": "d228302ac12860a0e92344756aa6eebff54ce171" + "reference": "e23298a1cd5e7745973ea26a53572a3d9b013439" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/c3/zipball/d228302ac12860a0e92344756aa6eebff54ce171", - "reference": "d228302ac12860a0e92344756aa6eebff54ce171", + "url": "https://api.github.com/repos/Codeception/c3/zipball/e23298a1cd5e7745973ea26a53572a3d9b013439", + "reference": "e23298a1cd5e7745973ea26a53572a3d9b013439", "shasum": "" }, "require": { "composer-plugin-api": "^1.0 || ^2.0", - "php": ">=5.4.0" + "php": ">=5.5.0" }, "require-dev": { "composer/composer": "^1.0 || ^2.0" @@ -316,22 +337,22 @@ ], "support": { "issues": "https://github.com/Codeception/c3/issues", - "source": "https://github.com/Codeception/c3/tree/2.6.5" + "source": "https://github.com/Codeception/c3/tree/2.9.0" }, - "time": "2022-04-28T12:08:33+00:00" + "time": "2023-10-15T17:57:07+00:00" }, { "name": "codeception/codeception", - "version": "4.2.1", + "version": "4.2.2", "source": { "type": "git", "url": "https://github.com/Codeception/Codeception.git", - "reference": "77b3e2003fd4446b35826cb9dc397129c521c888" + "reference": "b88014f3348c93f3df99dc6d0967b0dbfa804474" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/Codeception/zipball/77b3e2003fd4446b35826cb9dc397129c521c888", - "reference": "77b3e2003fd4446b35826cb9dc397129c521c888", + "url": "https://api.github.com/repos/Codeception/Codeception/zipball/b88014f3348c93f3df99dc6d0967b0dbfa804474", + "reference": "b88014f3348c93f3df99dc6d0967b0dbfa804474", "shasum": "" }, "require": { @@ -408,7 +429,7 @@ ], "support": { "issues": "https://github.com/Codeception/Codeception/issues", - "source": "https://github.com/Codeception/Codeception/tree/4.2.1" + "source": "https://github.com/Codeception/Codeception/tree/4.2.2" }, "funding": [ { @@ -416,26 +437,26 @@ "type": "open_collective" } ], - "time": "2022-06-22T06:18:59+00:00" + "time": "2022-08-13T13:28:25+00:00" }, { "name": "codeception/lib-asserts", - "version": "1.13.2", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/Codeception/lib-asserts.git", - "reference": "184231d5eab66bc69afd6b9429344d80c67a33b6" + "reference": "78c55044611437988b54e1daecf13f247a742bf8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/lib-asserts/zipball/184231d5eab66bc69afd6b9429344d80c67a33b6", - "reference": "184231d5eab66bc69afd6b9429344d80c67a33b6", + "url": "https://api.github.com/repos/Codeception/lib-asserts/zipball/78c55044611437988b54e1daecf13f247a742bf8", + "reference": "78c55044611437988b54e1daecf13f247a742bf8", "shasum": "" }, "require": { - "codeception/phpunit-wrapper": ">6.0.15 <6.1.0 | ^6.6.1 | ^7.7.1 | ^8.0.3 | ^9.0", + "codeception/phpunit-wrapper": "^7.7.1 | ^8.0.3 | ^9.0", "ext-dom": "*", - "php": ">=5.6.0 <9.0" + "php": "^7.4 | ^8.0" }, "type": "library", "autoload": { @@ -468,9 +489,9 @@ ], "support": { "issues": "https://github.com/Codeception/lib-asserts/issues", - "source": "https://github.com/Codeception/lib-asserts/tree/1.13.2" + "source": "https://github.com/Codeception/lib-asserts/tree/2.0.1" }, - "time": "2020-10-21T16:26:20+00:00" + "time": "2022-09-27T06:17:39+00:00" }, { "name": "codeception/phpbuiltinserver", @@ -563,24 +584,29 @@ "issues": "https://github.com/Codeception/phpunit-wrapper/issues", "source": "https://github.com/Codeception/phpunit-wrapper/tree/9.0.9" }, + "abandoned": true, "time": "2022-05-23T06:24:11+00:00" }, { "name": "codeception/stub", - "version": "3.7.0", + "version": "4.0.2", "source": { "type": "git", "url": "https://github.com/Codeception/Stub.git", - "reference": "468dd5fe659f131fc997f5196aad87512f9b1304" + "reference": "18a148dacd293fc7b044042f5aa63a82b08bff5d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/Stub/zipball/468dd5fe659f131fc997f5196aad87512f9b1304", - "reference": "468dd5fe659f131fc997f5196aad87512f9b1304", + "url": "https://api.github.com/repos/Codeception/Stub/zipball/18a148dacd293fc7b044042f5aa63a82b08bff5d", + "reference": "18a148dacd293fc7b044042f5aa63a82b08bff5d", "shasum": "" }, "require": { - "phpunit/phpunit": "^8.4 | ^9.0" + "php": "^7.4 | ^8.0", + "phpunit/phpunit": "^8.4 | ^9.0 | ^10.0 | 10.0.x-dev" + }, + "require-dev": { + "consolidation/robo": "^3.0" }, "type": "library", "autoload": { @@ -595,36 +621,36 @@ "description": "Flexible Stub wrapper for PHPUnit's Mock Builder", "support": { "issues": "https://github.com/Codeception/Stub/issues", - "source": "https://github.com/Codeception/Stub/tree/3.7.0" + "source": "https://github.com/Codeception/Stub/tree/4.0.2" }, - "time": "2020-07-03T15:54:43+00:00" + "time": "2022-01-31T19:25:15+00:00" }, { "name": "doctrine/instantiator", - "version": "1.5.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^9 || ^11", + "doctrine/coding-standard": "^11", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.16 || ^1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.30 || ^5.4" + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.9.4", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5.27", + "vimeo/psalm": "^5.4" }, "type": "library", "autoload": { @@ -651,7 +677,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.5.0" + "source": "https://github.com/doctrine/instantiator/tree/2.0.0" }, "funding": [ { @@ -667,7 +693,7 @@ "type": "tidelift" } ], - "time": "2022-12-30T00:15:36+00:00" + "time": "2022-12-30T00:23:10+00:00" }, { "name": "flow/jsonpath", @@ -832,16 +858,16 @@ }, { "name": "guzzlehttp/promises", - "version": "1.5.1", + "version": "1.5.3", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da" + "reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/fe752aedc9fd8fcca3fe7ad05d419d32998a06da", - "reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da", + "url": "https://api.github.com/repos/guzzle/promises/zipball/67ab6e18aaa14d753cc148911d273f6e6cb6721e", + "reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e", "shasum": "" }, "require": { @@ -851,11 +877,6 @@ "symfony/phpunit-bridge": "^4.4 || ^5.1" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.5-dev" - } - }, "autoload": { "files": [ "src/functions_include.php" @@ -896,7 +917,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/1.5.1" + "source": "https://github.com/guzzle/promises/tree/1.5.3" }, "funding": [ { @@ -912,7 +933,7 @@ "type": "tidelift" } ], - "time": "2021-10-22T20:56:57+00:00" + "time": "2023-05-21T12:31:43+00:00" }, { "name": "guzzlehttp/psr7", @@ -1232,30 +1253,37 @@ }, { "name": "nikic/php-parser", - "version": "v4.19.5", + "version": "v5.7.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "51bd93cc741b7fc3d63d20b6bdcd99fdaa359837" + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/51bd93cc741b7fc3d63d20b6bdcd99fdaa359837", - "reference": "51bd93cc741b7fc3d63d20b6bdcd99fdaa359837", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", "shasum": "" }, "require": { + "ext-ctype": "*", + "ext-json": "*", "ext-tokenizer": "*", - "php": ">=7.1" + "php": ">=7.4" }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^9.0" }, "bin": [ "bin/php-parse" ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, "autoload": { "psr-4": { "PhpParser\\": "lib/PhpParser" @@ -1277,9 +1305,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.19.5" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" }, - "time": "2025-12-06T11:45:25+00:00" + "time": "2025-12-06T11:56:16+00:00" }, { "name": "phar-io/manifest", @@ -1720,16 +1748,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.33", + "version": "9.6.34", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "fea06253ecc0a32faf787bd31b261f56f351d049" + "reference": "b36f02317466907a230d3aa1d34467041271ef4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fea06253ecc0a32faf787bd31b261f56f351d049", - "reference": "fea06253ecc0a32faf787bd31b261f56f351d049", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b36f02317466907a230d3aa1d34467041271ef4a", + "reference": "b36f02317466907a230d3aa1d34467041271ef4a", "shasum": "" }, "require": { @@ -1803,7 +1831,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.33" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.34" }, "funding": [ { @@ -1827,26 +1855,31 @@ "type": "tidelift" } ], - "time": "2026-01-27T05:25:09+00:00" + "time": "2026-01-27T05:45:00+00:00" }, { "name": "psr/container", - "version": "1.1.1", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", - "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", "shasum": "" }, "require": { - "php": ">=7.2.0" + "php": ">=7.4.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, "autoload": { "psr-4": { "Psr\\Container\\": "src/" @@ -1873,9 +1906,9 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.1" + "source": "https://github.com/php-fig/container/tree/2.0.2" }, - "time": "2021-03-05T17:36:06+00:00" + "time": "2021-11-05T16:47:00+00:00" }, { "name": "psr/event-dispatcher", @@ -3037,16 +3070,16 @@ }, { "name": "symfony/console", - "version": "v5.4.10", + "version": "v5.4.47", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "4d671ab4ddac94ee439ea73649c69d9d200b5000" + "reference": "c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/4d671ab4ddac94ee439ea73649c69d9d200b5000", - "reference": "4d671ab4ddac94ee439ea73649c69d9d200b5000", + "url": "https://api.github.com/repos/symfony/console/zipball/c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed", + "reference": "c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed", "shasum": "" }, "require": { @@ -3111,12 +3144,12 @@ "homepage": "https://symfony.com", "keywords": [ "cli", - "command line", + "command-line", "console", "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.10" + "source": "https://github.com/symfony/console/tree/v5.4.47" }, "funding": [ { @@ -3132,20 +3165,20 @@ "type": "tidelift" } ], - "time": "2022-06-26T13:00:04+00:00" + "time": "2024-11-06T11:30:55+00:00" }, { "name": "symfony/css-selector", - "version": "v5.4.3", + "version": "v5.4.45", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "b0a190285cd95cb019237851205b8140ef6e368e" + "reference": "4f7f3c35fba88146b56d0025d20ace3f3901f097" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/b0a190285cd95cb019237851205b8140ef6e368e", - "reference": "b0a190285cd95cb019237851205b8140ef6e368e", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/4f7f3c35fba88146b56d0025d20ace3f3901f097", + "reference": "4f7f3c35fba88146b56d0025d20ace3f3901f097", "shasum": "" }, "require": { @@ -3182,7 +3215,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v5.4.3" + "source": "https://github.com/symfony/css-selector/tree/v5.4.45" }, "funding": [ { @@ -3198,33 +3231,33 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2024-09-25T14:11:13+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v2.5.2", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.1" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { @@ -3249,7 +3282,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" }, "funding": [ { @@ -3265,20 +3298,20 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v5.4.9", + "version": "v5.4.45", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "8e6ce1cc0279e3ff3c8ff0f43813bc88d21ca1bc" + "reference": "72982eb416f61003e9bb6e91f8b3213600dcf9e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/8e6ce1cc0279e3ff3c8ff0f43813bc88d21ca1bc", - "reference": "8e6ce1cc0279e3ff3c8ff0f43813bc88d21ca1bc", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/72982eb416f61003e9bb6e91f8b3213600dcf9e9", + "reference": "72982eb416f61003e9bb6e91f8b3213600dcf9e9", "shasum": "" }, "require": { @@ -3334,7 +3367,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.9" + "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.45" }, "funding": [ { @@ -3350,37 +3383,34 @@ "type": "tidelift" } ], - "time": "2022-05-05T16:45:39+00:00" + "time": "2024-09-25T14:11:13+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v2.5.2", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1" + "reference": "59eb412e93815df44f05f342958efa9f46b1e586" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/f98b54df6ad059855739db6fcbc2d36995283fe1", - "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.1", "psr/event-dispatcher": "^1" }, - "suggest": { - "symfony/event-dispatcher-implementation": "" - }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { @@ -3413,7 +3443,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.2" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" }, "funding": [ { @@ -3429,20 +3459,20 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/finder", - "version": "v5.4.8", + "version": "v5.4.45", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "9b630f3427f3ebe7cd346c277a1408b00249dad9" + "reference": "63741784cd7b9967975eec610b256eed3ede022b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/9b630f3427f3ebe7cd346c277a1408b00249dad9", - "reference": "9b630f3427f3ebe7cd346c277a1408b00249dad9", + "url": "https://api.github.com/repos/symfony/finder/zipball/63741784cd7b9967975eec610b256eed3ede022b", + "reference": "63741784cd7b9967975eec610b256eed3ede022b", "shasum": "" }, "require": { @@ -3476,7 +3506,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v5.4.8" + "source": "https://github.com/symfony/finder/tree/v5.4.45" }, "funding": [ { @@ -3492,36 +3522,33 @@ "type": "tidelift" } ], - "time": "2022-04-15T08:07:45+00:00" + "time": "2024-09-28T13:32:08+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.26.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "433d05519ce6990bf3530fba6957499d327395c2" + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2", - "reference": "433d05519ce6990bf3530fba6957499d327395c2", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -3557,7 +3584,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" }, "funding": [ { @@ -3568,43 +3595,43 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2022-05-24T11:49:31+00:00" + "time": "2025-06-27T09:58:17+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.26.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8" + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/59a8d271f00dd0e4c2e518104cc7963f655a1aa8", - "reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3", "shasum": "" }, "require": { - "php": ">=7.1", - "symfony/polyfill-intl-normalizer": "^1.10", - "symfony/polyfill-php72": "^1.10" + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -3644,7 +3671,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.26.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0" }, "funding": [ { @@ -3655,41 +3682,42 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2022-05-24T11:49:31+00:00" + "time": "2024-09-10T14:38:51+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.26.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "219aa369ceff116e673852dce47c3a41794c14bd" + "reference": "3833d7255cc303546435cb650316bff708a1c75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd", - "reference": "219aa369ceff116e673852dce47c3a41794c14bd", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -3728,7 +3756,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" }, "funding": [ { @@ -3739,29 +3767,34 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2022-05-24T11:49:31+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.26.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e" + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", - "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", "shasum": "" }, "require": { - "php": ">=7.1" + "ext-iconv": "*", + "php": ">=7.2" }, "provide": { "ext-mbstring": "*" @@ -3771,12 +3804,9 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -3811,7 +3841,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" }, "funding": [ { @@ -3823,79 +3853,7 @@ "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-php72", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/bf44a9fd41feaac72b074de600314a93e2ae78e2", - "reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php72\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/nicolas-grekas", "type": "github" }, { @@ -3903,33 +3861,30 @@ "type": "tidelift" } ], - "time": "2022-05-24T11:49:31+00:00" + "time": "2024-12-23T08:48:59+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.26.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85" + "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/e440d35fa0286f77fb45b79a03fedbeda9307e85", - "reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f68c03565dcaaf25a890667542e8bd75fe7e5bb", + "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -3966,7 +3921,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.26.0" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.33.0" }, "funding": [ { @@ -3977,38 +3932,39 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2022-05-24T11:49:31+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.26.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace" + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace", - "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4049,7 +4005,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" }, "funding": [ { @@ -4060,52 +4016,56 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2022-05-10T07:21:04+00:00" + "time": "2025-01-02T08:10:11+00:00" }, { "name": "symfony/service-contracts", - "version": "v2.5.2", + "version": "v3.6.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", "shasum": "" }, "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1|^3" + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { "ext-psr": "<1.1|>=2" }, - "suggest": { - "symfony/service-implementation": "" - }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -4132,7 +4092,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.1" }, "funding": [ { @@ -4143,43 +4103,46 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2022-05-30T19:17:29+00:00" + "time": "2025-07-15T11:30:57+00:00" }, { "name": "symfony/string", - "version": "v5.4.10", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "4432bc7df82a554b3e413a8570ce2fea90e94097" + "reference": "2adaf4106f2ef4c67271971bde6d3fe0a6936432" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/4432bc7df82a554b3e413a8570ce2fea90e94097", - "reference": "4432bc7df82a554b3e413a8570ce2fea90e94097", + "url": "https://api.github.com/repos/symfony/string/zipball/2adaf4106f2ef4c67271971bde6d3fe0a6936432", + "reference": "2adaf4106f2ef4c67271971bde6d3fe0a6936432", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "~1.15" + "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/translation-contracts": ">=3.0" + "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/translation-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0|^6.0" + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/intl": "^6.2|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -4218,7 +4181,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.10" + "source": "https://github.com/symfony/string/tree/v6.4.34" }, "funding": [ { @@ -4229,12 +4192,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2022-06-26T15:57:47+00:00" + "time": "2026-02-08T20:44:54+00:00" }, { "name": "theseer/tokenizer", @@ -4297,7 +4264,7 @@ "composer-plugin-api": "^2.0" }, "platform-overrides": { - "php": "7.3" + "php": "8.3" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/controller/preview.php b/controller/preview.php index 5d3c7245c5..404fab4356 100644 --- a/controller/preview.php +++ b/controller/preview.php @@ -56,7 +56,7 @@ trait Preview { protected function exitController() { if (\defined('PHPUNIT_RUN')) { throw new \Exception(); - // @codeCoverageIgnoreStart + // @codeCoverageIgnoreStart } else { exit(); } diff --git a/templates/index.php b/templates/index.php index 839e367aaa..af551e7ea1 100644 --- a/templates/index.php +++ b/templates/index.php @@ -16,5 +16,5 @@ } else { print_unescaped($this->inc('part.content')); } - ?> +?> diff --git a/templates/part.content.php b/templates/part.content.php index b43b129bff..1852b23c54 100644 --- a/templates/part.content.php +++ b/templates/part.content.php @@ -72,21 +72,21 @@
<?php p($l->t('Sort by date')); ?> + image_path($_['appName'], 'dateasc.svg') + ); ?>" alt="t('Sort by date')); ?>"/> <?php p($l->t('Sort by date')); ?> + image_path($_['appName'], 'datedes.svg') + ); ?>" alt="t('Sort by date')); ?>"/>
<?php p($l->t('Sort by name')); ?> + image_path($_['appName'], 'nameasc.svg') + ); ?>" alt="t('Sort by name')); ?>"/> <?php p($l->t('Sort by name')); ?> + image_path($_['appName'], 'namedes.svg') + ); ?>" alt="t('Sort by name')); ?>"/>
@@ -105,8 +105,8 @@
<?php p($l->t("/> + image_path('core', 'actions/share.svg') + ); ?>" alt="t("Share")); ?>"/>
@@ -134,8 +134,8 @@ class="icon-confirm svg" disabled>
<?php p($l->t('Album information')); ?> + image_path('core', 'actions/info.svg') + ); ?>" alt="t('Album information')); ?>"/>
@@ -145,8 +145,8 @@ class="icon-confirm svg" disabled>
diff --git a/tests/unit/middleware/EnvCheckMiddlewareTest.php b/tests/unit/middleware/EnvCheckMiddlewareTest.php index d6d99f0211..a3c4513984 100644 --- a/tests/unit/middleware/EnvCheckMiddlewareTest.php +++ b/tests/unit/middleware/EnvCheckMiddlewareTest.php @@ -708,8 +708,8 @@ private function mockShareManagerGetShareByTokenThrowsException($token) { ->with($token) ->willThrowException( new \OCP\Share\Exceptions\ShareNotFound( - "Can't find a share using that token" - ) + "Can't find a share using that token" + ) ); } diff --git a/vendor-bin/owncloud-codestyle/composer.json b/vendor-bin/owncloud-codestyle/composer.json index 2d5dfea6b8..f3e61e6548 100644 --- a/vendor-bin/owncloud-codestyle/composer.json +++ b/vendor-bin/owncloud-codestyle/composer.json @@ -1,5 +1,5 @@ { "require": { - "owncloud/coding-standard": "^3.0" + "owncloud/coding-standard": "^5.3" } } From 55b57d166570ef701674b3da86239b5e3fc42e5b Mon Sep 17 00:00:00 2001 From: Phillip Davis Date: Thu, 26 Mar 2026 20:35:02 +0930 Subject: [PATCH 2/6] chore: try passing special app setup command --- .github/workflows/main.yml | 6 +- .github/workflows/php-unit.yml | 193 +++++++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/php-unit.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ea9344aa7a..7d848638e6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -19,6 +19,7 @@ concurrency: env: APP_NAME: gallery + SPECIAL_APP_SETUP_COMMAND: composer install PHP_VERSIONS: '["8.3"]' jobs: @@ -26,11 +27,13 @@ jobs: runs-on: ubuntu-latest outputs: app-name: ${{ env.APP_NAME }} + special-app-setup-command: ${{ env.SPECIAL_APP_SETUP_COMMAND }} php-versions: ${{ env.PHP_VERSIONS }} steps: - name: Set variables run: | echo "App name $APP_NAME" + echo "Special App Setup Command: $SPECIAL_APP_SETUP_COMMAND" echo "PHP versions string: $PHP_VERSIONS" semantic-git-messages: @@ -50,7 +53,8 @@ jobs: name: PHP Unit needs: - get-vars - uses: owncloud/reusable-workflows/.github/workflows/php-unit.yml@main + uses: ./.github/workflows/php-unit.yml with: app-name: ${{ needs.get-vars.outputs.app-name }} + special-app-setup-command: ${{ needs.get-vars.outputs.special-app-setup-command }} php-versions: ${{ needs.get-vars.outputs.php-versions }} diff --git a/.github/workflows/php-unit.yml b/.github/workflows/php-unit.yml new file mode 100644 index 0000000000..21d5047fd6 --- /dev/null +++ b/.github/workflows/php-unit.yml @@ -0,0 +1,193 @@ +on: + workflow_call: + inputs: + app-name: + description: 'Name of the app' + required: true + type: string + php-versions: + description: JSON array of PHP versions + required: true + type: string + app-repository: + description: 'Repository of the app (optional, defaults to the current repository)' + required: false + type: string + default: '' + do-integration-tests: + description: 'Whether to run PHP integration tests' + required: false + type: boolean + default: false + additional-app: + description: 'Additional app to enable for testing' + required: false + type: string + default: '' + additional-app-github-token: + description: 'GitHub PAT to access the additional app repo - required if private' + required: false + type: string + default: '' + additional-packages: + description: Additional Linux packages to be installed - space separated + required: false + type: string + default: '' + special-app-setup-command: + description: 'Command that needs to be executed after the app is checked out and PHP is available' + required: false + type: string + default: '' + +jobs: + php-unit: + name: PHP Unit + runs-on: ubuntu-latest + strategy: + fail-fast: true + matrix: + php: ${{ fromJSON(inputs.php-versions) }} + database: [sqlite] + include: + - php: ${{ fromJSON(inputs.php-versions)[0] }} + database: "mysql:8.0" + - php: ${{ fromJSON(inputs.php-versions)[0] }} + database: "mariadb:10.6" + - php: ${{ fromJSON(inputs.php-versions)[0] }} + database: "postgres:10.21" + + services: + mysql: + image: >- + ${{ (startsWith(matrix.database,'mysql:') || startsWith(matrix.database,'mariadb:')) && matrix.database || '' }} + env: + MYSQL_ROOT_PASSWORD: password + MYSQL_DATABASE: owncloud + MYSQL_USER: owncloud + MYSQL_PASSWORD: owncloud + options: >- + --health-cmd="mysqladmin ping -u root -ppassword" + --health-interval=10s + --health-timeout=5s + --health-retries=3 + ports: + - 3306:3306 + postgres: + image: ${{ startsWith(matrix.database,'postgres:') && matrix.database || '' }} + env: + POSTGRES_DB: owncloud + POSTGRES_USER: owncloud + POSTGRES_PASSWORD: owncloud + ports: + - 5432:5432 + + steps: + - name: Clone owncloud/core + uses: actions/checkout@v6 + with: + repository: owncloud/core + + - name: Checkout apps/${{ inputs.app-name }} + uses: actions/checkout@v6 + with: + path: apps/${{ inputs.app-name }} + repository: ${{ inputs.app-repository }} + + - name: Checkout apps/${{ inputs.additional-app }} + if: ${{ inputs.additional-app != '' }} + uses: actions/checkout@v6 + with: + path: apps/${{ inputs.additional-app }} + repository: owncloud/${{ inputs.additional-app }} + token: ${{ inputs.additional-app-github-token || github.token }} + + - name: Install Linux packages + if: ${{ inputs.additional-packages }} + run: | + sudo apt-get install ${{ inputs.additional-packages }} + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: apcu, ctype, curl, exif, fileinfo, gd, iconv, imagick, intl, json, mbstring, memcached, pdo, posix, simplexml, xml, zip, smbclient, ldap, krb5 + ini-values: "memory_limit=1024M" + env: + fail-fast: true + KRB5_LINUX_LIBS: libkrb5-dev + + - name: Install Core Dependencies + run: | + make + + - name: Special app setup/${{ inputs.app-name }} + if: ${{ inputs.special-app-setup-command != '' }} + run: | + cd apps/${{ inputs.app-name }} + ${{ inputs.special-app-setup-command }} + + - name: Install Server + env: + DATA_DIRECTORY: ${{ github.workspace }}/data + DB: ${{ matrix.database }} + DB_NAME: owncloud + ADMIN_LOGIN: admin + ADMIN_PASSWORD: admin + DB_HOST: 127.0.0.1 + DB_USERNAME: owncloud + DB_PASSWORD: owncloud + + run: | + DB_TYPE=${DB%:*} + if [ $DB_TYPE == "postgres" ] ; then DB_TYPE="pgsql"; fi + if [ $DB_TYPE == "mariadb" ] ; then DB_TYPE="mysql"; fi + install_cmd="maintenance:install -vvv \ + --database=${DB_TYPE} \ + --database-name=${DB_NAME} \ + --admin-user=${ADMIN_LOGIN} \ + --admin-pass=${ADMIN_PASSWORD} \ + --data-dir=${DATA_DIRECTORY} " + + if [[ "${DB_TYPE}" != "sqlite" ]]; then + install_cmd+=" --database-host=${DB_HOST} \ + --database-user=${DB_USERNAME} \ + --database-pass=${DB_PASSWORD}" + fi + + php occ ${install_cmd} + echo "enabling apps" + php occ app:enable files_sharing + php occ app:enable files_trashbin + php occ app:enable files_versions + php occ app:enable provisioning_api + php occ app:enable federation + php occ app:enable federatedfilesharing + + - name: Setup apps/${{ inputs.additional-app }} + if: ${{ inputs.additional-app != '' }} + run: | + ( cd apps/${{ inputs.additional-app }} && make vendor || true) + php occ a:e ${{ inputs.additional-app }} + + - name: Setup apps/${{ inputs.app-name }} + run: | + ( cd apps/${{ inputs.app-name }} && make vendor || true) + php occ a:e ${{ inputs.app-name }} + + - name: Run PHPUnit + run: | + cd apps/${{ inputs.app-name }} + make test-php-unit + + - name: Run PHP Integration tests + if: ${{ inputs.do-integration-tests }} + run: | + cd apps/${{ inputs.app-name }} + make test-php-integration + + - name: Tail log + if: always() + run: | + ls -la data + cat data/owncloud.log From 9a8fe48e8dd433b7e81c261cebfa46acef368ef3 Mon Sep 17 00:00:00 2001 From: Phillip Davis Date: Thu, 26 Mar 2026 20:51:36 +0930 Subject: [PATCH 3/6] fix: initialise features property in FilesService --- service/filesservice.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/filesservice.php b/service/filesservice.php index d0a5453d4d..0d58f24474 100644 --- a/service/filesservice.php +++ b/service/filesservice.php @@ -27,7 +27,7 @@ abstract class FilesService extends Service { /** @var int */ protected $virtualRootLevel = null; /** @var string[] */ - protected $features; + protected $features = []; /** @var string */ protected $ignoreAlbum = '.nomedia'; From fdc5da3426efe762befa3f4db7766f38036bc921 Mon Sep 17 00:00:00 2001 From: Phillip Davis Date: Thu, 26 Mar 2026 20:55:42 +0930 Subject: [PATCH 4/6] fix: iitialise supportedMediaTypes property --- service/searchmediaservice.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/searchmediaservice.php b/service/searchmediaservice.php index 1d5bba07bd..8769919cce 100644 --- a/service/searchmediaservice.php +++ b/service/searchmediaservice.php @@ -27,7 +27,7 @@ class SearchMediaService extends FilesService { /** @var null|array */ private $albums = []; /** @var string[] */ - private $supportedMediaTypes; + private $supportedMediaTypes = []; /** * This returns the list of all media files which can be shown starting from the given folder From 5cde83b5f3358b0e83b1ec32bb76bf40ed20ea39 Mon Sep 17 00:00:00 2001 From: Phillip Davis Date: Thu, 26 Mar 2026 21:04:08 +0930 Subject: [PATCH 5/6] chore(ci): pass special-app-setup-command to php-codestyle --- .github/workflows/main.yml | 3 +- .github/workflows/php-codestyle.yml | 154 ++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/php-codestyle.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7d848638e6..94c9d1e9ad 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -44,9 +44,10 @@ jobs: name: PHP Code Style needs: - get-vars - uses: owncloud/reusable-workflows/.github/workflows/php-codestyle.yml@main + uses: ./.github/workflows/php-codestyle.yml with: app-name: ${{ needs.get-vars.outputs.app-name }} + special-app-setup-command: ${{ needs.get-vars.outputs.special-app-setup-command }} php-versions: ${{ needs.get-vars.outputs.php-versions }} php-unit: diff --git a/.github/workflows/php-codestyle.yml b/.github/workflows/php-codestyle.yml new file mode 100644 index 0000000000..fd304b4113 --- /dev/null +++ b/.github/workflows/php-codestyle.yml @@ -0,0 +1,154 @@ +on: + workflow_call: + inputs: + app-name: + description: 'Name of the app' + required: true + type: string + php-versions: + description: JSON array of PHP versions + required: true + type: string + app-repository: + description: 'Repository of the app (optional, defaults to the current repository)' + required: false + type: string + default: '' + disable-phpstan: + description: 'Whether to disable PHPStan checks' + required: false + type: boolean + default: false + disable-phan: + description: 'Whether to disable Phan checks' + required: false + type: boolean + default: false + additional-app: + description: 'Additional app to enable for testing' + required: false + type: string + default: '' + additional-app-github-token: + description: 'GitHub PAT to access the additional app repo - required if private' + required: false + type: string + default: '' + additional-packages: + description: Additional Linux packages to be installed - space separated + required: false + type: string + default: '' + special-app-setup-command: + description: 'Command that needs to be executed after the app is checked out and PHP is available' + required: false + type: string + default: '' + +jobs: + php-codestyle: + name: PHP Code Style + runs-on: ubuntu-latest + strategy: + fail-fast: true + matrix: + php: ${{ fromJSON(inputs.php-versions) }} + + steps: + - name: Clone owncloud/core + uses: actions/checkout@v6 + with: + repository: owncloud/core + + - name: Checkout apps/${{ inputs.app-name }} + uses: actions/checkout@v6 + with: + path: apps/${{ inputs.app-name }} + repository: ${{ inputs.app-repository }} + + - name: Checkout apps/${{ inputs.additional-app }} + if: ${{ inputs.additional-app != '' }} + uses: actions/checkout@v6 + with: + path: apps/${{ inputs.additional-app }} + repository: owncloud/${{ inputs.additional-app }} + token: ${{ inputs.additional-app-github-token || github.token }} + + - name: Install Linux packages + if: ${{ inputs.additional-packages }} + run: | + sudo apt-get install ${{ inputs.additional-packages }} + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: apcu, ctype, curl, exif, fileinfo, gd, iconv, imagick, intl, json, mbstring, memcached, pdo, posix, simplexml, xml, zip, smbclient, ldap, krb5 + ini-values: "memory_limit=1024M" + env: + fail-fast: true + KRB5_LINUX_LIBS: libkrb5-dev + + - name: Install Core Dependencies + run: | + make + + - name: Special app setup/${{ inputs.app-name }} + if: ${{ inputs.special-app-setup-command != '' }} + run: | + cd apps/${{ inputs.app-name }} + ${{ inputs.special-app-setup-command }} + + - name: Install Server + env: + DATA_DIRECTORY: ${{ github.workspace }}/data + DB_TYPE: "sqlite" + DB_NAME: owncloud + ADMIN_LOGIN: admin + ADMIN_PASSWORD: admin + + run: | + install_cmd="maintenance:install -vvv \ + --database=${DB_TYPE} \ + --database-name=${DB_NAME} \ + --admin-user=${ADMIN_LOGIN} \ + --admin-pass=${ADMIN_PASSWORD} \ + --data-dir=${DATA_DIRECTORY} " + + php occ ${install_cmd} + echo "enabling apps" + php occ app:enable files_sharing + php occ app:enable files_trashbin + php occ app:enable files_versions + php occ app:enable provisioning_api + php occ app:enable federation + php occ app:enable federatedfilesharing + + - name: Setup apps/${{ inputs.additional-app }} + if: ${{ inputs.additional-app != '' }} + run: | + ( cd apps/${{ inputs.additional-app }} && make vendor || true) + php occ a:e ${{ inputs.additional-app }} + + - name: Setup apps/${{ inputs.app-name }} + run: | + ( cd apps/${{ inputs.app-name }} && make vendor || true) + php occ a:e ${{ inputs.app-name }} + + - name: Run PHP Code Style Checks + run: | + cd apps/${{ inputs.app-name }} + make test-php-style + + - name: Run PHP Stan + if: ${{ !inputs.disable-phpstan }} + run: | + cd apps/${{ inputs.app-name }} + make test-php-phpstan + + - name: Run PHP Phan + if: ${{ !inputs.disable-phan }} + run: | + cd apps/${{ inputs.app-name }} + make test-php-phan + From a77301c688111929d65bb22a639bcc5dd3de9ba3 Mon Sep 17 00:00:00 2001 From: Phillip Davis Date: Thu, 26 Mar 2026 21:09:25 +0930 Subject: [PATCH 6/6] chore(ci): disable phpstan and phan --- .github/workflows/main.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 94c9d1e9ad..9672d5a772 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -49,6 +49,8 @@ jobs: app-name: ${{ needs.get-vars.outputs.app-name }} special-app-setup-command: ${{ needs.get-vars.outputs.special-app-setup-command }} php-versions: ${{ needs.get-vars.outputs.php-versions }} + disable-phpstan: true + disable-phan: true php-unit: name: PHP Unit