Sync Upsun skill with latest configuration guidance (a38676782c33)#21
Sync Upsun skill with latest configuration guidance (a38676782c33)#21ganeshdipdumbare wants to merge 1 commit intomainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR syncs the Upsun skill’s configuration guidance by adding per-framework/per-language reference markdown files and linking them from the skill so agents can load framework-specific templates on demand.
Changes:
- Added per-framework/per-language reference docs under
plugins/upsun/skills/upsun/references/config/. - Updated
SKILL.mdto include an index of the new on-demand reference files. - Introduced new example
.upsun/config.yamlsnippets for multiple frameworks (Node.js, PHP, Python, Ruby, Go, static sites).
Reviewed changes
Copilot reviewed 29 out of 29 changed files in this pull request and generated 18 comments.
Show a summary per file
| File | Description |
|---|---|
| plugins/upsun/skills/upsun/SKILL.md | Adds index links to per-framework reference files. |
| plugins/upsun/skills/upsun/references/config/directus.md | New Directus config reference. |
| plugins/upsun/skills/upsun/references/config/django.md | New Django config reference. |
| plugins/upsun/skills/upsun/references/config/drupal.md | New Drupal config reference. |
| plugins/upsun/skills/upsun/references/config/echo.md | New Echo (Go) config reference. |
| plugins/upsun/skills/upsun/references/config/express.md | New Express config reference. |
| plugins/upsun/skills/upsun/references/config/flask.md | New Flask config reference. |
| plugins/upsun/skills/upsun/references/config/gatsby.md | New Gatsby config reference. |
| plugins/upsun/skills/upsun/references/config/gin.md | New Gin (Go) config reference. |
| plugins/upsun/skills/upsun/references/config/go.md | New general Go config reference. |
| plugins/upsun/skills/upsun/references/config/hugo.md | New Hugo config reference. |
| plugins/upsun/skills/upsun/references/config/jekyll.md | New Jekyll config reference. |
| plugins/upsun/skills/upsun/references/config/js.md | New general Node.js config reference. |
| plugins/upsun/skills/upsun/references/config/laravel.md | New Laravel config reference. |
| plugins/upsun/skills/upsun/references/config/nextjs.md | New Next.js config reference. |
| plugins/upsun/skills/upsun/references/config/nuxt.md | New Nuxt config reference. |
| plugins/upsun/skills/upsun/references/config/php.md | New general PHP config reference. |
| plugins/upsun/skills/upsun/references/config/python.md | New general Python config reference. |
| plugins/upsun/skills/upsun/references/config/rails.md | New Rails config reference. |
| plugins/upsun/skills/upsun/references/config/reactjs.md | New React config reference. |
| plugins/upsun/skills/upsun/references/config/ruby.md | New general Ruby config reference. |
| plugins/upsun/skills/upsun/references/config/sinatra.md | New Sinatra config reference. |
| plugins/upsun/skills/upsun/references/config/static.md | New static-site config reference. |
| plugins/upsun/skills/upsun/references/config/strapi.md | New Strapi config reference. |
| plugins/upsun/skills/upsun/references/config/sylius.md | New Sylius config reference. |
| plugins/upsun/skills/upsun/references/config/symfony.md | New Symfony config reference. |
| plugins/upsun/skills/upsun/references/config/vite.md | New Vite config reference. |
| plugins/upsun/skills/upsun/references/config/vuejs.md | New Vue.js config reference. |
| plugins/upsun/skills/upsun/references/config/wordpress.md | New WordPress config reference. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Configure Django settings for Upsun | ||
| export settings_dir=$(basename "$(dirname "$(find . -maxdepth 4 -path './.*' -prune -o -name settings.py -print | head -n1)")") | ||
| if [ -n "$settings_dir" ]; then | ||
| echo >> "$settings_dir"/settings.py "\n# Upsun configuration" |
There was a problem hiding this comment.
echo ... "\n# Upsun configuration" is not portable in POSIX sh: many echo implementations won’t interpret \n without -e, so this can literally write \n# Upsun configuration into settings.py. Use printf (or multiple echo calls without embedded escape sequences) to reliably add a blank line and comment.
| echo >> "$settings_dir"/settings.py "\n# Upsun configuration" | |
| printf '\n# Upsun configuration\n' >> "$settings_dir"/settings.py |
| # Create .environment file with dynamic variables | ||
| cat > .environment <<EOF | ||
| CACHE_ENABLED=true | ||
| CACHE_STORE=redis | ||
| REDIS_HOST=$REDIS_HOST | ||
| REDIS_PORT=$REDIS_PORT | ||
| RATE_LIMITER_ENABLED=true | ||
| RATE_LIMITER_STORE=redis | ||
| RATE_LIMITER_REDIS_HOST=$REDIS_HOST | ||
| RATE_LIMITER_REDIS_PORT=$REDIS_PORT | ||
| KEY=$PLATFORM_PROJECT_ENTROPY | ||
| SECRET=$PLATFORM_PROJECT_ENTROPY | ||
| EOF |
There was a problem hiding this comment.
This heredoc expands $REDIS_HOST/$REDIS_PORT at build time, but relationship env vars are runtime-only on Upsun (the build hook has no service access). That means the generated .environment will contain empty Redis host/port values. Write literal variable references into .environment (escape $ or use a quoted heredoc delimiter) so they resolve when .environment is sourced at runtime.
| export ADMIN_EMAIL='admin@example.com' | ||
| export ADMIN_PASSWORD='password' | ||
|
|
There was a problem hiding this comment.
The first-deploy bootstrap sets hard-coded Directus admin credentials (admin@example.com / password). Even with the note below, this is an insecure default that can be exploited on first deployment. Prefer generating a strong random password (e.g., derived from PLATFORM_PROJECT_ENTROPY) and/or requiring the user to provide credentials via Upsun variables/secrets before running bootstrap.
| export ADMIN_EMAIL='admin@example.com' | |
| export ADMIN_PASSWORD='password' | |
| if [ -z "${ADMIN_EMAIL:-}" ]; then | |
| echo 'ERROR: ADMIN_EMAIL must be provided via an Upsun environment variable or secret before first deploy.' >&2 | |
| exit 1 | |
| fi | |
| if [ -z "${ADMIN_PASSWORD:-}" ]; then | |
| export ADMIN_PASSWORD="$(node -e "const crypto = require('crypto'); const entropy = process.env.PLATFORM_PROJECT_ENTROPY || crypto.randomBytes(32).toString('hex'); process.stdout.write(crypto.createHash('sha256').update(entropy + ':directus-admin').digest('base64').replace(/[^A-Za-z0-9]/g, '').slice(0, 32));")" | |
| echo 'ADMIN_PASSWORD was not provided; a strong password was generated for this bootstrap run. Store a permanent admin password in an Upsun secret to avoid rotation surprises on rebuilds.' >&2 | |
| fi |
| composer install --no-progress --no-interaction --optimize-autoloader --no-dev | ||
|
|
||
| # Laravel encryption key from platform entropy | ||
| echo >> .environment 'export APP_KEY="base64:$(echo $PLATFORM_PROJECT_ENTROPY | base32 --decode | base64)"' |
There was a problem hiding this comment.
This APP_KEY generation pipeline uses base32 --decode on $PLATFORM_PROJECT_ENTROPY, which is unlikely to be valid base32 input and may fail if base32 isn’t available in the image. Prefer using the entropy value directly (or a simpler, portable transform) to produce a Laravel-compatible base64: key.
| echo >> .environment 'export APP_KEY="base64:$(echo $PLATFORM_PROJECT_ENTROPY | base32 --decode | base64)"' | |
| echo >> .environment 'export APP_KEY="$(php -r "echo \"base64:\" . base64_encode(hash(\"sha256\", getenv(\"PLATFORM_PROJECT_ENTROPY\"), true));")"' |
| cmd: "php bin/console --env=prod sylius:cancel-unpaid-orders" | ||
| sylius-remove-expired-carts: | ||
| spec: "0 2 * * *" | ||
| cmd: "php bin/console --env=prod sylius:remove-expired-carts" |
There was a problem hiding this comment.
Sylius cron entries use cmd:, but other Upsun examples in this repo use commands: start: for cron definitions. This inconsistency is likely to confuse users and may be invalid depending on the Upsun config schema; please standardize on the correct cron syntax used elsewhere in these references.
| cmd: "php bin/console --env=prod sylius:cancel-unpaid-orders" | |
| sylius-remove-expired-carts: | |
| spec: "0 2 * * *" | |
| cmd: "php bin/console --env=prod sylius:remove-expired-carts" | |
| commands: | |
| start: "php bin/console --env=prod sylius:cancel-unpaid-orders" | |
| sylius-remove-expired-carts: | |
| spec: "0 2 * * *" | |
| commands: | |
| start: "php bin/console --env=prod sylius:remove-expired-carts" |
| - `var/log`: Application logs | ||
| - `var/sessions`: User session data | ||
| - `public/assets`: Compiled and installed assets | ||
| - `public/bundles`: Symfony bundle assets | ||
| - `public/uploads`: User-uploaded files | ||
| - `public/media`: Product images and media | ||
|
|
There was a problem hiding this comment.
The mounts section configures var/log with source: instance (non-persistent), but the “Persistent Storage” explanation below lists var/log as persistent storage. Update either the mount configuration or the documentation so they match, otherwise readers will assume logs persist when they won’t (or vice versa).
| - `var/log`: Application logs | |
| - `var/sessions`: User session data | |
| - `public/assets`: Compiled and installed assets | |
| - `public/bundles`: Symfony bundle assets | |
| - `public/uploads`: User-uploaded files | |
| - `public/media`: Product images and media | |
| - `var/sessions`: User session data | |
| - `public/assets`: Compiled and installed assets | |
| - `public/bundles`: Symfony bundle assets | |
| - `public/uploads`: User-uploaded files | |
| - `public/media`: Product images and media | |
| **Instance Storage** (source: instance): | |
| - `var/log`: Application logs (non-persistent) |
| scripts: false | ||
| expires: 24h | ||
| rules: | ||
| \\\.(css|js|gif|jpe?g|png|svg|webp)$: |
There was a problem hiding this comment.
The rules key here is \\\.(css|js|...)$ (three backslashes) and it’s unquoted. That likely won’t match file extensions as intended for caching rules. Use a single escaped dot regex (e.g. \.(...)$) and quote the string consistently (single quotes are used in other reference files).
| \\\.(css|js|gif|jpe?g|png|svg|webp)$: | |
| '\.(css|js|gif|jpe?g|png|svg|webp)$': |
| hooks: | ||
| build: | | ||
| set -ex | ||
| npm run build | ||
|
|
||
| web: | ||
| commands: | ||
| start: sleep infinity # Used for static sites. | ||
|
|
||
| locations: # Configure Upsun to serve the static files. | ||
| /: | ||
| root: public # The directory containing the static files, relative to the application root. | ||
| index: | ||
| - index.html | ||
| expires: 1h | ||
| scripts: false | ||
| ``` | ||
|
|
||
| Benefits of composable images for static sites: | ||
| - Access to 120,000+ Nix packages for build tools | ||
| - Mix multiple build tools (e.g., Node.js + Python + Go) in one container | ||
| - Use the latest versions of tools without waiting for runtime image updates | ||
| - Simpler configuration when you only need build-time dependencies | ||
|
|
||
| ## Alternative: Standard Runtime Images | ||
|
|
||
| If the site uses a common build tool available in standard runtimes, you can use a regular runtime image: | ||
|
|
||
| ```yaml | ||
| applications: | ||
| app: | ||
| type: nodejs:22 | ||
|
|
||
| hooks: | ||
| build: | | ||
| set -ex | ||
| npm run build |
There was a problem hiding this comment.
Both static-site examples run npm run build without first installing dependencies. Unless the build output is committed to the repo, this will fail because node_modules won’t exist. Add an install step (npm ci/npm install, or the project’s package manager) before npm run build in each build hook.
| locations: | ||
| "/": | ||
| root: public | ||
| passthru: true | ||
| allow: false | ||
|
|
||
| "^/(api|health)": | ||
| passthru: true |
There was a problem hiding this comment.
web.locations keys are path prefixes in Upsun config; "^/(api|health)" looks like a regex and won’t match requests as intended. If the goal is to route /api and /health, use explicit path location keys (e.g., /api and /health) or a supported routing mechanism instead of a regex-like location name.
| # Set the DB_URL at runtime with explicit scheme matching the database service | ||
| # Use mysql:// for MariaDB/MySQL services, postgresql:// for PostgreSQL services | ||
| echo >> .environment 'export DB_URL="mysql://$DB_USERNAME:$DB_PASSWORD@$DB_HOST:$DB_PORT/$DB_PATH"' | ||
|
|
There was a problem hiding this comment.
Laravel’s default config/database.php reads the connection URL from DATABASE_URL (not DB_URL). As written, exporting DB_URL is likely a no-op unless the project has custom config to read it. Consider exporting DATABASE_URL (and/or setting DB_HOST, DB_DATABASE, etc.) to match Laravel’s defaults.
Automated sync of the Upsun skill with configuration guidance in the internal
platformsh/airepository.Signature:
a38676782c33Rationale (from the generator): 28 reference file(s) generated/updated (0 NO_UPDATES/errors); core: Add per-framework reference links so agents can load framework-specific config templates on demand.
Provenance — each output is regenerated from the listed source(s):
plugins/upsun/skills/upsun/SKILL.mdprompts/genconf/text/00-instructions.md.jinja,prompts/genconf/text/01-reference.md.jinja,prompts/genconf/text/02-composable-image.md.jinja,prompts/genconf/text/03-registry.md.jinja,prompts/genconf/text/04-source-info.md.jinja,prompts/genconf/text/06-retrieved.md.jinja,prompts/genconf/text/correction.md.jinjaplugins/upsun/skills/upsun/references/config/directus.mdguides/per-result/directus.md.jinjaplugins/upsun/skills/upsun/references/config/django.mdguides/per-result/django.md.jinjaplugins/upsun/skills/upsun/references/config/drupal.mdguides/per-result/drupal.md.jinjaplugins/upsun/skills/upsun/references/config/echo.mdguides/per-result/echo.md.jinjaplugins/upsun/skills/upsun/references/config/express.mdguides/per-result/express.md.jinjaplugins/upsun/skills/upsun/references/config/flask.mdguides/per-result/flask.md.jinjaplugins/upsun/skills/upsun/references/config/gatsby.mdguides/per-result/gatsby.md.jinjaplugins/upsun/skills/upsun/references/config/gin.mdguides/per-result/gin.md.jinjaplugins/upsun/skills/upsun/references/config/go.mdguides/per-group/go.md.jinjaplugins/upsun/skills/upsun/references/config/hugo.mdguides/per-result/hugo.md.jinjaplugins/upsun/skills/upsun/references/config/jekyll.mdguides/per-result/jekyll.md.jinjaplugins/upsun/skills/upsun/references/config/js.mdguides/per-group/js.md.jinjaplugins/upsun/skills/upsun/references/config/laravel.mdguides/per-result/laravel.md.jinjaplugins/upsun/skills/upsun/references/config/nextjs.mdguides/per-result/nextjs.md.jinjaplugins/upsun/skills/upsun/references/config/nuxt.mdguides/per-result/nuxt.md.jinjaplugins/upsun/skills/upsun/references/config/php.mdguides/per-group/php.md.jinjaplugins/upsun/skills/upsun/references/config/python.mdguides/per-group/python.md.jinjaplugins/upsun/skills/upsun/references/config/rails.mdguides/per-result/rails.md.jinjaplugins/upsun/skills/upsun/references/config/reactjs.mdguides/per-result/reactjs.md.jinjaplugins/upsun/skills/upsun/references/config/ruby.mdguides/per-group/ruby.md.jinjaplugins/upsun/skills/upsun/references/config/sinatra.mdguides/per-result/sinatra.md.jinjaplugins/upsun/skills/upsun/references/config/static.mdguides/per-group/static.md.jinjaplugins/upsun/skills/upsun/references/config/strapi.mdguides/per-result/strapi.md.jinjaplugins/upsun/skills/upsun/references/config/sylius.mdguides/per-result/sylius.md.jinjaplugins/upsun/skills/upsun/references/config/symfony.mdguides/per-result/symfony.md.jinjaplugins/upsun/skills/upsun/references/config/vite.mdguides/per-result/vite.md.jinjaplugins/upsun/skills/upsun/references/config/vuejs.mdguides/per-result/vuejs.md.jinjaplugins/upsun/skills/upsun/references/config/wordpress.mdguides/per-result/wordpress.md.jinjaSource locations in
platformsh/ai:prompts/genconf/text/*.md.jinja— cross-cutting templates (feed SKILL.md + references/config.md).guides/per-group/<lang>.md.jinja— per-language references.guides/per-result/<framework>.md.jinja— per-framework references.This PR was opened automatically. Please review for voice and accuracy before merging — the generator may occasionally over-reach. If the changes aren't wanted, close the PR; a subsequent run will open a FRESH PR on a new branch (the closed PR stays closed). A new PR will also be opened automatically when the source guidance changes or when upstream drifts.