Skip to content

add test app#5

Open
kaz29 wants to merge 1 commit intomainfrom
feat/testapp
Open

add test app#5
kaz29 wants to merge 1 commit intomainfrom
feat/testapp

Conversation

@kaz29
Copy link
Copy Markdown
Owner

@kaz29 kaz29 commented Mar 28, 2026

No description provided.

@kaz29 kaz29 requested a review from Copilot March 28, 2026 08:23
@kaz29 kaz29 self-assigned this Mar 28, 2026
@kaz29 kaz29 added the enhancement New feature or request label Mar 28, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a full CakePHP “testapp” demo application to validate the plugin’s OpenTelemetry instrumentation end-to-end (CRUD + DB + error handling), including local Docker tooling and Azure (Bicep) deployment docs.

Changes:

  • Adds a CakePHP 5 demo app (Posts/Comments CRUD) wired to the OTel plugin and middleware.
  • Adds local dev environment via Docker Compose (PostgreSQL + Jaeger) and production/dev Dockerfiles.
  • Adds Azure IaC (Bicep) and step-by-step specs for infra, deployment, and verification.

Reviewed changes

Copilot reviewed 89 out of 128 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
README.md Documents the included testapp demo app and quick-start steps
README.ja.md Japanese README updates incl. demo app section
testapp/.gitignore Ignores app-local config, vendor, tmp/logs, IDE artifacts for the demo app
testapp/Dockerfile Production image build for demo app (PHP-FPM + Nginx + supervisord)
testapp/Dockerfile.dev Dev image build for demo app (volume-mounted source)
testapp/README.md Demo app README (local + Azure deployment)
testapp/compose.yaml Local dev stack (app + postgres + jaeger)
testapp/composer.json Demo app dependencies (CakePHP + migrations + OTel plugin) and scripts
testapp/composer.lock Locked dependency graph for demo app
testapp/index.php Entrypoint delegating to webroot/index.php
testapp/phpcs.xml PHPCS ruleset for demo app
testapp/phpstan.neon PHPStan config for demo app
testapp/phpunit.xml.dist PHPUnit configuration for demo app
testapp/psalm.xml Psalm configuration for demo app
testapp/supervisord.pid Supervisord PID file (currently committed)
testapp/bicep/main.bicep Main Azure deployment template wiring modules together
testapp/bicep/main.json Generated ARM JSON output for the Bicep template
testapp/bicep/parameters.bicepparam Parameter file for Bicep deployment
testapp/bicep/modules/acr.bicep Azure Container Registry module
testapp/bicep/modules/ca.bicep Azure Container App module incl. env vars (DB + OTel)
testapp/bicep/modules/cae.bicep Container Apps Environment module
testapp/bicep/modules/log.bicep Log Analytics + Application Insights module
testapp/bicep/modules/postgres.bicep PostgreSQL Flexible Server module
testapp/bin/bash_completion.sh Bash completion script for Cake console
testapp/bin/cake Shell wrapper for Cake console
testapp/bin/cake.bat Windows batch wrapper for Cake console
testapp/bin/cake.php PHP entry for Cake console runner
testapp/config/.env.example Example env vars for local configuration (incl. base URL + salt placeholders)
testapp/config/app.php Base CakePHP app config (incl. fullBaseUrl env + logging)
testapp/config/app_local.example.php Example local overrides (DB + debug + salt)
testapp/config/bootstrap.php App bootstrap incl. fullBaseUrl handling and framework setup
testapp/config/paths.php Defines core path constants
testapp/config/plugins.php Plugin load configuration (DebugKit/Bake/Migrations)
testapp/config/routes.php Routes (maps / to Posts index; includes Pages routes and fallbacks)
testapp/config/Migrations/20260328000000_CreatePosts.php Migration to create posts table
testapp/config/Migrations/20260328000001_CreateComments.php Migration to create comments table (FK to posts)
testapp/config/Migrations/schema-dump-default.lock Schema dump lock file
testapp/config/schema/i18n.sql Optional i18n schema
testapp/config/schema/sessions.sql Optional DB sessions schema
testapp/docker/nginx/default.conf Nginx vhost config for CakePHP front controller
testapp/docker/php/php-production.ini Production PHP settings (opcache, expose_php off)
testapp/docker/php/www-overrides.conf PHP-FPM pool override (clear_env)
testapp/docker/supervisor/supervisord.conf Supervisord config to run php-fpm + nginx
testapp/plugins/.gitkeep Keeps plugins dir in repo
testapp/resources/.gitkeep Keeps resources dir in repo
testapp/specs/00-overview.md Overall project overview/spec
testapp/specs/01-application.md Step 1 spec: app construction (models/controllers/views/OTel)
testapp/specs/02-docker.md Step 2 spec: dockerization approach
testapp/specs/03-infrastructure.md Step 3 spec: Azure infra via Bicep
testapp/specs/04-deployment.md Step 4 spec: CI/CD + deployment flow
testapp/specs/05-verification.md Step 5 spec: OTel verification steps (Jaeger + App Insights)
testapp/src/Application.php App bootstrap + middleware queue (ErrorHandler + OTel + HostHeader + routing + CSRF)
testapp/src/Console/Installer.php Composer install hooks (create app_local, perms, salt)
testapp/src/Controller/AppController.php Base controller loading Flash component
testapp/src/Controller/CommentsController.php Comment add/delete actions
testapp/src/Controller/ErrorController.php Error controller wiring error template path
testapp/src/Controller/PagesController.php Static pages controller w/ traversal protection
testapp/src/Controller/PostsController.php Posts CRUD actions with pagination
testapp/src/Controller/Component/.gitkeep Keeps Component dir in repo
testapp/src/Middleware/HostHeaderMiddleware.php Validates Host header against configured base URL in production
testapp/src/Model/Behavior/.gitkeep Keeps Behavior dir in repo
testapp/src/Model/Entity/.gitkeep Keeps Entity dir in repo
testapp/src/Model/Entity/Comment.php Comment entity accessible fields
testapp/src/Model/Entity/Post.php Post entity accessible fields
testapp/src/Model/Table/.gitkeep Keeps Table dir in repo
testapp/src/Model/Table/CommentsTable.php Comments table config + validation + belongsTo Posts
testapp/src/Model/Table/PostsTable.php Posts table config + validation + hasMany Comments
testapp/src/View/AjaxView.php AJAX view that switches layout and response type
testapp/src/View/AppView.php Base AppView
testapp/src/View/Cell/.gitkeep Keeps View Cell dir in repo
testapp/src/View/Helper/.gitkeep Keeps View Helper dir in repo
testapp/templates/Error/error400.php 400 error template
testapp/templates/Error/error500.php 500 error template
testapp/templates/Pages/home.php Debug home page with environment checks and DebugKit/DB status
testapp/templates/Posts/add.php Post create form template
testapp/templates/Posts/edit.php Post edit form template
testapp/templates/Posts/index.php Post list template with paginator
testapp/templates/Posts/view.php Post detail template + comments listing + comment form
testapp/templates/cell/.gitkeep Keeps templates/cell dir in repo
testapp/templates/element/flash/default.php Default flash element
testapp/templates/element/flash/error.php Error flash element
testapp/templates/element/flash/info.php Info flash element
testapp/templates/element/flash/success.php Success flash element
testapp/templates/element/flash/warning.php Warning flash element
testapp/templates/email/html/default.php HTML email template
testapp/templates/email/text/default.php Text email template
testapp/templates/layout/ajax.php Ajax layout
testapp/templates/layout/default.php Default layout (nav + container + assets)
testapp/templates/layout/error.php Error layout
testapp/templates/layout/email/html/default.php HTML email layout wrapper
testapp/templates/layout/email/text/default.php Text email layout wrapper
testapp/tests/bootstrap.php Test bootstrap (autoload, app bootstrap, migrations, fixed time/session id)
testapp/tests/schema.sql Placeholder schema file for tests (if not using migrations)
testapp/tests/Fixture/.gitkeep Keeps Fixture dir in repo
testapp/tests/TestCase/ApplicationTest.php Tests for bootstrap/plugin loading + middleware order
testapp/tests/TestCase/Controller/PagesControllerTest.php Integration tests for Pages controller and CSRF behavior
testapp/tests/TestCase/Controller/Component/.gitkeep Keeps controller component tests dir
testapp/tests/TestCase/Model/Behavior/.gitkeep Keeps model behavior tests dir
testapp/tests/TestCase/View/Helper/.gitkeep Keeps view helper tests dir
testapp/webroot/.htaccess Rewrite rule for Apache setups
testapp/webroot/favicon.ico App favicon
testapp/webroot/index.php Front controller for all web requests
testapp/webroot/js/.gitkeep Keeps webroot JS dir
testapp/webroot/css/cake.css App UI styling and overrides
testapp/webroot/css/fonts.css Raleway font-face declarations
testapp/webroot/css/home.css Home page styling
testapp/webroot/css/milligram.min.css Milligram CSS (minified)
testapp/webroot/css/normalize.min.css Normalize CSS (minified)
testapp/webroot/font/Raleway-License.txt Font license file
testapp/webroot/font/cakedingbats-webfont.eot Cake dingbats font
testapp/webroot/font/cakedingbats-webfont.svg Cake dingbats font
testapp/webroot/font/cakedingbats-webfont.ttf Cake dingbats font
testapp/webroot/font/cakedingbats-webfont.woff Cake dingbats font
testapp/webroot/font/cakedingbats-webfont.woff2 Cake dingbats font
testapp/webroot/font/raleway-400-cyrillic-ext.woff2 Raleway font subset
testapp/webroot/font/raleway-400-cyrillic.woff2 Raleway font subset
testapp/webroot/font/raleway-400-latin-ext.woff2 Raleway font subset
testapp/webroot/font/raleway-400-latin.woff2 Raleway font subset
testapp/webroot/font/raleway-400-vietnamese.woff2 Raleway font subset
testapp/webroot/font/raleway-700-cyrillic-ext.woff2 Raleway font subset
testapp/webroot/font/raleway-700-cyrillic.woff2 Raleway font subset
testapp/webroot/font/raleway-700-latin-ext.woff2 Raleway font subset
testapp/webroot/font/raleway-700-latin.woff2 Raleway font subset
testapp/webroot/font/raleway-700-vietnamese.woff2 Raleway font subset
testapp/webroot/img/cake-logo.png CakePHP logo asset
testapp/webroot/img/cake.icon.png CakePHP icon asset
testapp/webroot/img/cake.logo.svg CakePHP SVG logo asset
testapp/webroot/img/cake.power.gif CakePHP “powered by” asset

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +77 to +82
{ name: 'OTEL_TRACES_EXPORTER', value: 'otlp' }
{ name: 'OTEL_EXPORTER_OTLP_PROTOCOL', value: 'http/protobuf' }
{ name: 'OTEL_EXPORTER_OTLP_ENDPOINT', value: 'https://japaneast-0.in.applicationinsights.azure.com/v2/track' }
{ name: 'OTEL_EXPORTER_OTLP_HEADERS', value: 'x-ms-client-request-id=${appInsightsConnectionString}' }
{ name: 'OTEL_LOGS_EXPORTER', value: 'otlp' }
{ name: 'OTEL_METRICS_EXPORTER', value: 'none' }
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The OpenTelemetry environment variables here don’t appear to match the configured OTLP exporter/protocol:

  • OTEL_EXPORTER_OTLP_PROTOCOL is set to http/protobuf, but OTEL_EXPORTER_OTLP_ENDPOINT is set to an Application Insights /v2/track endpoint, which is not an OTLP HTTP endpoint.
  • OTEL_EXPORTER_OTLP_HEADERS is set to x-ms-client-request-id=<connection-string>, but the OTLP exporter expects auth/connection headers relevant to the OTLP endpoint; a connection string also contains semicolons which can break header parsing.

This will likely prevent traces/logs from being exported. Consider using the correct OTLP ingestion endpoint + required authorization header(s), or switch to Azure Monitor’s supported OpenTelemetry distribution/configuration for Application Insights ingestion.

Suggested change
{ name: 'OTEL_TRACES_EXPORTER', value: 'otlp' }
{ name: 'OTEL_EXPORTER_OTLP_PROTOCOL', value: 'http/protobuf' }
{ name: 'OTEL_EXPORTER_OTLP_ENDPOINT', value: 'https://japaneast-0.in.applicationinsights.azure.com/v2/track' }
{ name: 'OTEL_EXPORTER_OTLP_HEADERS', value: 'x-ms-client-request-id=${appInsightsConnectionString}' }
{ name: 'OTEL_LOGS_EXPORTER', value: 'otlp' }
{ name: 'OTEL_METRICS_EXPORTER', value: 'none' }
{ name: 'APPLICATIONINSIGHTS_CONNECTION_STRING', value: appInsightsConnectionString }

Copilot uses AI. Check for mistakes.
docker compose up -d
```

`http://localhost:8765` でアクセス。
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documented local URL doesn’t match the Docker Compose port mapping. compose.yaml publishes the app on http://localhost:8080, but this README says http://localhost:8765.

Please update the README to reflect the actual exposed port (or adjust compose.yaml if 8765 is intended).

Suggested change
`http://localhost:8765` でアクセス。
`http://localhost:8080` でアクセス。

Copilot uses AI. Check for mistakes.
* You should treat it as extremely sensitive data.
*/
'Security' => [
'salt' => env('SECURITY_SALT', '8e367f0c2c16e5179e1720da4e18b791b11b5e3c1bc156592f8298d042d8367f'),
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Installer::setSecuritySaltInFile() replaces the __SALT__ placeholder in config/app_local.php, but config/app_local.example.php currently hardcodes a default salt value instead of containing the __SALT__ placeholder. As a result, new installs that rely on the installer will keep the same shared salt unless SECURITY_SALT is set externally.

To keep the installer effective (and avoid insecure shared defaults), consider changing the example to use the __SALT__ placeholder (or otherwise ensure the installer updates the salt deterministically).

Suggested change
'salt' => env('SECURITY_SALT', '8e367f0c2c16e5179e1720da4e18b791b11b5e3c1bc156592f8298d042d8367f'),
'salt' => env('SECURITY_SALT', '__SALT__'),

Copilot uses AI. Check for mistakes.
Comment on lines +16 to +18
RUN composer install --no-dev --optimize-autoloader --no-interaction

COPY . .
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The build stage runs composer install before the application source (including src/Console/Installer.php and config/app_local.example.php) is copied into the image. Because composer.json defines post-install-cmd as App\Console\Installer::postInstall, this is very likely to fail (class/file not found) or skip generating config/app_local.php.

Consider either copying the minimal app files needed by the scripts (e.g., src/Console/Installer.php + config/app_local.example.php) before composer install, or running composer install --no-scripts in the cached layer and executing the necessary setup steps after COPY . ..

Suggested change
RUN composer install --no-dev --optimize-autoloader --no-interaction
COPY . .
RUN composer install --no-dev --optimize-autoloader --no-interaction --no-scripts
COPY . .
RUN composer run-script post-install-cmd --no-interaction

Copilot uses AI. Check for mistakes.
Comment on lines +38 to +54
$fullBaseUrl = Configure::read('App.fullBaseUrl');
if (!$fullBaseUrl) {
throw new InternalErrorException(
'SECURITY: App.fullBaseUrl is not configured. ' .
'This is required in production to prevent Host Header Injection attacks. ' .
'Set APP_FULL_BASE_URL environment variable or configure App.fullBaseUrl in config/app.php',
);
}

$configuredHost = parse_url($fullBaseUrl, PHP_URL_HOST);
$requestHost = $request->getUri()->getHost();

if ($configuredHost && $requestHost && strtolower($configuredHost) !== strtolower($requestHost)) {
throw new BadRequestException(
'Invalid Host header. Request host does not match configured application host.',
);
}
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If App.fullBaseUrl is misconfigured (e.g., missing scheme) parse_url($fullBaseUrl, PHP_URL_HOST) can return null/false. In that case the middleware silently skips host validation and allows requests through, which undermines the intended Host header injection protection.

Suggestion: treat a missing/invalid host from parse_url() as a configuration error (throw InternalErrorException), and only proceed when a valid configured host is present.

Copilot uses AI. Check for mistakes.
Comment on lines +32 to +57
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
if (Configure::read('debug')) {
return $handler->handle($request);
}

$fullBaseUrl = Configure::read('App.fullBaseUrl');
if (!$fullBaseUrl) {
throw new InternalErrorException(
'SECURITY: App.fullBaseUrl is not configured. ' .
'This is required in production to prevent Host Header Injection attacks. ' .
'Set APP_FULL_BASE_URL environment variable or configure App.fullBaseUrl in config/app.php',
);
}

$configuredHost = parse_url($fullBaseUrl, PHP_URL_HOST);
$requestHost = $request->getUri()->getHost();

if ($configuredHost && $requestHost && strtolower($configuredHost) !== strtolower($requestHost)) {
throw new BadRequestException(
'Invalid Host header. Request host does not match configured application host.',
);
}

return $handler->handle($request);
}
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This middleware is security-critical, but there are no tests covering its behavior (e.g., throws when debug is false and App.fullBaseUrl is missing, rejects mismatched Host headers, allows matching hosts). Adding a focused test case would help prevent regressions and make the expected production behavior explicit.

Copilot uses AI. Check for mistakes.
Comment on lines +18 to +22
$lines = explode("\n", $content);

foreach ($lines as $line) :
echo '<p> ' . $line . "</p>\n";
endforeach;
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$line is inserted into HTML without escaping. If $content can include user-provided data, this enables HTML/script injection in HTML emails.

Consider escaping each line (e.g., using h($line)) before wrapping it in <p>, or otherwise ensuring the content is sanitized/HTML-safe by construction.

Copilot uses AI. Check for mistakes.
@@ -0,0 +1 @@
1
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A PID file should not be committed to the repository. Keeping supervisord.pid under version control can confuse local/dev/prod process supervision and is likely to be overwritten at runtime.

Remove this file from the repo and add it to .gitignore (or configure supervisord to write its PID under a runtime directory like /var/run).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants