diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d14e084..dd94f16 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -59,6 +59,108 @@ jobs: cd ./test-server composer test:unit + test-database-config: + name: Test Database Configuration + runs-on: ubuntu-latest + services: + mongo: + image: mongo:7 + ports: + - 27017:27017 + steps: + - uses: actions/checkout@v6.0.2 + + - name: Test action with database configuration + uses: ./ + with: + install-php: 'true' + php-version: '8.5' + server-path: './test-server' + database-uri: 'mongodb://127.0.0.1:27017/?tls=false' + database-name: 'ktrix_ci' + app-environment: 'test' + + - name: Verify configuration was written + run: | + cd ./test-server + php -r ' + $config = include "config/system.php"; + $uri = $config["database"]["uri"] ?? null; + $name = $config["database"]["database"] ?? null; + $env = $config["environment"] ?? null; + if ($uri !== "mongodb://127.0.0.1:27017/?tls=false") { fwrite(STDERR, "database.uri not overridden, got: $uri\n"); exit(1); } + if ($name !== "ktrix_ci") { fwrite(STDERR, "database.database not overridden, got: $name\n"); exit(1); } + if ($env !== "test") { fwrite(STDERR, "environment not overridden, got: $env\n"); exit(1); } + ' + echo "✓ Database configuration verified" + + - name: Verify database is reachable with configured settings + run: | + cd ./test-server + php bin/console tenant:list + + test-base-modules: + name: Test Base Modules Installation + runs-on: ubuntu-latest + services: + mongo: + image: mongo:7 + ports: + - 27017:27017 + steps: + - uses: actions/checkout@v6.0.2 + + - name: Test action with base modules + uses: ./ + with: + install-php: 'true' + php-version: '8.5' + server-path: './test-server' + database-uri: 'mongodb://127.0.0.1:27017/?tls=false' + database-name: 'ktrix_ci' + install-base-modules: 'true' + + - name: Verify password authentication provider is installed and enabled + run: | + cd ./test-server + OUTPUT=$(php bin/console module:list) + echo "$OUTPUT" + echo "$OUTPUT" | grep -q "authentication_provider_password" || { echo "::error::authentication_provider_password not found in module list"; exit 1; } + echo "$OUTPUT" | grep "authentication_provider_password" | grep -q "Enabled" || { echo "::error::authentication_provider_password is not enabled"; exit 1; } + echo "✓ authentication_provider_password is installed and enabled" + + - name: Verify a tenant and user can be provisioned end-to-end + run: | + cd ./test-server + php bin/console tenant:create ci.test --identifier ci_smoke + php bin/console user:create ci_smoke tester@ci.test + php bin/console user:password ci_smoke tester@ci.test 'Sup3r-Secret!' + php bin/console user:list ci_smoke | grep -q "tester@ci.test" || { echo "::error::provisioned user not found"; exit 1; } + echo "✓ tenant and user provisioning verified" + + test-base-modules-requires-php: + name: Test Base Modules Requires PHP + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6.0.2 + + - name: Expect failure when install-base-modules is set without install-php + id: expect-failure + continue-on-error: true + uses: ./ + with: + install-node: 'true' + install-base-modules: 'true' + server-path: './test-server' + + - name: Verify the action failed + run: | + if [ "${{ steps.expect-failure.outcome }}" != "failure" ]; then + echo "::error::Expected action to fail when install-base-modules is set without install-php" + exit 1 + fi + echo "✓ Action correctly rejected install-base-modules without install-php" + test-nginx: name: Test nginx runs-on: ubuntu-latest diff --git a/README.md b/README.md index 54dbef0..b6a1146 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,57 @@ jobs: npm run test:integration ``` +### With Database Configuration + +Point the checked-out server at a database (e.g. a `mongo` service container) and write the value into `config/system.php` before dependencies or base modules are installed: + +```yaml +services: + mongo: + image: mongo:7 + ports: + - 27017:27017 + +steps: + - name: Install server with database configuration + uses: Nodarx/action-server-install@v1 + with: + install-php: 'true' + database-uri: 'mongodb://127.0.0.1:27017/?tls=false' + database-name: 'ktrix_ci' + app-environment: 'test' +``` + +Any override left blank keeps the value already committed in `config/system.php`. + +### With Base Modules (Password Authentication) + +`install-base-modules` clones the password authentication provider module (from `base-modules-repository`, via [action-module-install](https://git.ktrix.dev/Nodarx/action-module-install)), then installs and enables it with `bin/console`. This requires PHP and a reachable, configured database: + +```yaml +services: + mongo: + image: mongo:7 + ports: + - 27017:27017 + +steps: + - name: Install server with base modules + uses: Nodarx/action-server-install@v1 + with: + install-php: 'true' + database-uri: 'mongodb://127.0.0.1:27017/?tls=false' + database-name: 'ktrix_ci' + install-base-modules: 'true' + + - name: Provision a tenant and user for testing + run: | + cd server + php bin/console tenant:create ci.test --identifier ci + php bin/console user:create ci tester@ci.test + php bin/console user:password ci tester@ci.test 'Sup3r-Secret!' +``` + ### With Custom nginx Configuration ```yaml @@ -159,6 +210,27 @@ jobs: |-------|-------------|----------|---------| | `nginx-config` | Path to nginx configuration file | No | `''` | +### Server Settings Configuration + +Overrides are written into the checked-out `config/system.php`. Requires `install-php: 'true'`; any input left blank keeps the repository's committed default. + +| Input | Description | Required | Default | +|-------|-------------|----------|---------| +| `database-uri` | MongoDB connection URI | No | `''` | +| `database-name` | MongoDB database name | No | `''` | +| `app-environment` | Application environment, e.g. `test` | No | `''` | +| `security-salt` | Security salt | No | `''` | + +### Base Modules + +Delegates cloning to [action-module-install](https://git.ktrix.dev/Nodarx/action-module-install), then installs and enables the module via `bin/console`. Requires `install-php` and a reachable, configured database. + +| Input | Description | Required | Default | +|-------|-------------|----------|---------| +| `install-base-modules` | Clone, install, and enable the base module set (currently: `authentication_provider_password`) | No | `false` | +| `base-modules-repository` | Repository URL for the password authentication provider module | No | `https://git.ktrix.dev/Nodarx/authentication_provider_password` | +| `base-modules-branch` | Branch, tag, or commit to check out for the password authentication provider module | No | `main` | + ## Outputs | Output | Description | @@ -168,6 +240,7 @@ jobs: | `node-installed` | Whether Node.js was installed (true/false) | | `php-installed` | Whether PHP was installed (true/false) | | `nginx-installed` | Whether nginx was installed (true/false) | +| `base-modules-installed` | Whether the base module set was installed (true/false) | ## Best Practices diff --git a/action.yml b/action.yml index 2ae4aef..3be105c 100644 --- a/action.yml +++ b/action.yml @@ -67,6 +67,34 @@ inputs: description: 'Optional token for private/external repository checkout' required: false default: '' + database-uri: + description: 'MongoDB connection URI to write into config/system.php (requires install-php; leave empty to keep the repository default)' + required: false + default: '' + database-name: + description: 'MongoDB database name to write into config/system.php (requires install-php; leave empty to keep the repository default)' + required: false + default: '' + app-environment: + description: 'Application environment to write into config/system.php, e.g. "test" (requires install-php; leave empty to keep the repository default)' + required: false + default: '' + security-salt: + description: 'Security salt to write into config/system.php (requires install-php; leave empty to keep the repository default)' + required: false + default: '' + install-base-modules: + description: 'Clone, install, and enable the base module set (currently: authentication_provider_password). Requires install-php and a reachable, configured database.' + required: false + default: 'false' + base-modules-repository: + description: 'Repository URL for the base password authentication provider module (used when install-base-modules is true)' + required: false + default: 'https://git.ktrix.dev/Nodarx/authentication_provider_password' + base-modules-branch: + description: 'Branch, tag, or commit to check out for the base password authentication provider module' + required: false + default: 'main' outputs: install-status: @@ -84,6 +112,9 @@ outputs: nginx-installed: description: 'Whether nginx was installed' value: ${{ steps.install.outputs.nginx_installed }} + base-modules-installed: + description: 'Whether the base module set was installed' + value: ${{ steps.install.outputs.base_modules_installed }} runs: using: 'composite' @@ -100,7 +131,13 @@ runs: echo "::error::At least one component must be enabled (install-node, install-php, or install-nginx)" exit 1 fi - + + # install-base-modules requires PHP (it runs bin/console) + if [ "${{ inputs.install-base-modules }}" == "true" ] && [ "${{ inputs.install-php }}" != "true" ]; then + echo "::error::install-base-modules requires install-php to be 'true'" + exit 1 + fi + echo "Server path: ${{ inputs.server-path }}" echo "Components to install:" [ "${{ inputs.install-node }}" == "true" ] && echo " ✓ Node.js ${{ inputs.node-version }}" @@ -147,6 +184,25 @@ runs: tools: composer:v2 coverage: none + - name: Configure server settings + if: inputs.install-php == 'true' + shell: bash + env: + DATABASE_URI: ${{ inputs.database-uri }} + DATABASE_NAME: ${{ inputs.database-name }} + APP_ENVIRONMENT: ${{ inputs.app-environment }} + SECURITY_SALT: ${{ inputs.security-salt }} + run: | + echo "::group::Configuring server settings" + + if [ -z "$DATABASE_URI$DATABASE_NAME$APP_ENVIRONMENT$SECURITY_SALT" ]; then + echo "No configuration overrides provided, keeping repository defaults." + else + php "${{ github.action_path }}/scripts/configure-server.php" "${{ inputs.server-path }}/config/system.php" + fi + + echo "::endgroup::" + - name: Install nginx if: inputs.install-nginx == 'true' shell: bash @@ -210,6 +266,34 @@ runs: echo "✓ PHP dependencies installed successfully" echo "::endgroup::" + - name: Clone base modules + if: inputs.install-base-modules == 'true' + uses: Nodarx/action-module-install@main + with: + modules: | + [ + { + "name": "authentication_provider_password", + "repo": "${{ inputs.base-modules-repository }}", + "branch": "${{ inputs.base-modules-branch }}" + } + ] + install-path: ${{ inputs.server-path }}/modules + + - name: Install and enable base modules + if: inputs.install-base-modules == 'true' + shell: bash + run: | + echo "::group::Installing base modules" + cd "${{ inputs.server-path }}" + + echo "Installing authentication_provider_password..." + php bin/console module:install authentication_provider_password + php bin/console module:enable authentication_provider_password + + echo "✓ Base modules installed" + echo "::endgroup::" + - name: Run build command if: inputs.build-command != '' shell: bash @@ -238,3 +322,4 @@ runs: echo "node_installed=${{ inputs.install-node }}" >> $GITHUB_OUTPUT echo "php_installed=${{ inputs.install-php }}" >> $GITHUB_OUTPUT echo "nginx_installed=${{ inputs.install-nginx }}" >> $GITHUB_OUTPUT + echo "base_modules_installed=${{ inputs.install-base-modules }}" >> $GITHUB_OUTPUT diff --git a/scripts/configure-server.php b/scripts/configure-server.php new file mode 100644 index 0000000..f40d97e --- /dev/null +++ b/scripts/configure-server.php @@ -0,0 +1,70 @@ +#!/usr/bin/env php + + * + * All overrides are read from environment variables and are optional; an + * unset or empty variable leaves the corresponding config value untouched: + * DATABASE_URI -> $config['database']['uri'] + * DATABASE_NAME -> $config['database']['database'] + * APP_ENVIRONMENT -> $config['environment'] + * SECURITY_SALT -> $config['security.salt'] + */ + +$path = $argv[1] ?? null; + +if (!$path || !is_file($path)) { + fwrite(STDERR, "Configuration file not found: {$path}\n"); + exit(1); +} + +$config = include $path; + +if (!is_array($config)) { + fwrite(STDERR, "Configuration file did not return an array: {$path}\n"); + exit(1); +} + +// Nested overrides: env var => [top-level key, nested key] +$nestedOverrides = [ + 'DATABASE_URI' => ['database', 'uri'], + 'DATABASE_NAME' => ['database', 'database'], +]; + +foreach ($nestedOverrides as $env => [$group, $key]) { + $value = getenv($env); + if ($value === false || $value === '') { + continue; + } + $config[$group][$key] = $value; + echo " - {$group}.{$key} overridden\n"; +} + +// Flat overrides: env var => config key +$flatOverrides = [ + 'APP_ENVIRONMENT' => 'environment', + 'SECURITY_SALT' => 'security.salt', +]; + +foreach ($flatOverrides as $env => $key) { + $value = getenv($env); + if ($value === false || $value === '') { + continue; + } + $config[$key] = $value; + echo " - {$key} overridden\n"; +} + +$export = var_export($config, true); +file_put_contents($path, "