├── config └── sync │ └── .gitkeep ├── web ├── .gitignore ├── .eslintrc.json ├── INSTALL.txt ├── .eslintignore ├── sites │ ├── development.services.yml │ ├── README.txt │ ├── default │ │ ├── settings.php │ │ └── settings.platformsh.php │ ├── example.sites.php │ └── example.settings.local.php ├── index.php ├── update.php ├── profiles │ └── README.txt ├── .csslintrc ├── themes │ └── README.txt ├── example.gitignore ├── modules │ └── README.txt ├── robots.txt ├── .ht.router.php ├── README.md ├── web.config └── .htaccess ├── .platform ├── last.updated ├── services.yaml └── routes.yaml ├── .github ├── ISSUE_TEMPLATE │ ├── config.yaml │ ├── improvements.yaml │ └── bug_report.yaml ├── workflows │ ├── project-issues.yaml │ ├── post-pr-acceptance.yaml │ ├── sourceops.yaml │ ├── autopr.yaml │ ├── testprenvironment.yaml │ └── workflow-fail-log.yaml ├── PULL_REQUEST_TEMPLATE.md └── tests │ └── vrt │ └── template-paths.js ├── php.ini ├── .environment ├── .gitignore ├── drush ├── platformsh_deploy_drupal.sh └── platformsh_generate_drush_yml.php ├── .lando.upstream.yml ├── header.svg ├── .blackfire.yml ├── .ddev ├── providers │ └── platform.yaml └── config.yml ├── composer.json ├── .platform.app.yaml └── README.md /config/sync/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/.gitignore: -------------------------------------------------------------------------------- 1 | /autoload.php -------------------------------------------------------------------------------- /.platform/last.updated: -------------------------------------------------------------------------------- 1 | Thu Dec 18 19:40:55 UTC 2025 2 | -------------------------------------------------------------------------------- /web/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./core/.eslintrc.json" 3 | } 4 | -------------------------------------------------------------------------------- /web/INSTALL.txt: -------------------------------------------------------------------------------- 1 | 2 | Please read core/INSTALL.txt for detailed installation instructions for your 3 | Drupal website. 4 | -------------------------------------------------------------------------------- /web/.eslintignore: -------------------------------------------------------------------------------- 1 | core/**/* 2 | vendor/**/* 3 | sites/**/files/**/* 4 | libraries/**/* 5 | sites/**/libraries/**/* 6 | profiles/**/libraries/**/* 7 | **/js_test_files/**/* 8 | **/node_modules/**/* 9 | -------------------------------------------------------------------------------- /.platform/services.yaml: -------------------------------------------------------------------------------- 1 | # The services of the project. 2 | # 3 | # Each service listed will be deployed 4 | # to power your Platform.sh project. 5 | 6 | db: 7 | type: mariadb:10.11 8 | disk: 2048 9 | 10 | cache: 11 | type: redis:7.2 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yaml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Community Support 4 | url: https://community.platform.sh/ 5 | about: Please ask and answer questions here. 6 | - name: Join us on Slack 7 | url: https://chat.platform.sh/ 8 | about: Ping the `@devrel_team`! 9 | -------------------------------------------------------------------------------- /web/sites/development.services.yml: -------------------------------------------------------------------------------- 1 | # Local development services. 2 | # 3 | # To activate this feature, follow the instructions at the top of the 4 | # 'example.settings.local.php' file, which sits next to this file. 5 | parameters: 6 | http.response.debug_cacheability_headers: true 7 | services: 8 | cache.backend.null: 9 | class: Drupal\Core\Cache\NullBackendFactory 10 | -------------------------------------------------------------------------------- /php.ini: -------------------------------------------------------------------------------- 1 | assert.active = Off 2 | display_errors = Off 3 | display_startup_errors = Off 4 | max_execution_time = 30 5 | session.use_strict_mode = On 6 | zend.detect_unicode = Off 7 | opcache.memory_consumption = 128 8 | opcache.interned_strings_buffer = 8 9 | opcache.max_accelerated_files = 4000 10 | opcache.revalidate_freq = 60 11 | opcache.fast_shutdown = 1 12 | opcache.enable_cli = 1 13 | realpath_cache_ttl = 3600 14 | session.gc_probability = 0 15 | -------------------------------------------------------------------------------- /.platform/routes.yaml: -------------------------------------------------------------------------------- 1 | # The routes of the project. 2 | # 3 | # Each route describes how an incoming URL is going 4 | # to be processed by Platform.sh. 5 | 6 | "https://{default}/": 7 | type: upstream 8 | upstream: "drupal:http" 9 | cache: 10 | enabled: true 11 | 12 | # Base the cache on the session cookie and custom Drupal cookies. Ignore all other cookies. 13 | cookies: ['/^SS?ESS/', '/^Drupal.visitor/'] 14 | 15 | "https://www.{default}/": 16 | type: redirect 17 | to: "https://{default}/" 18 | -------------------------------------------------------------------------------- /web/sites/README.txt: -------------------------------------------------------------------------------- 1 | This directory structure contains the settings and configuration files specific 2 | to your site or sites and is an integral part of multisite configurations. 3 | 4 | It is now recommended to place your custom and downloaded extensions in the 5 | /modules, /themes, and /profiles directories located in the Drupal root. The 6 | sites/all/ subdirectory structure, which was recommended in previous versions 7 | of Drupal, is still supported. 8 | 9 | See core/INSTALL.txt for information about single-site installation or 10 | multisite configuration. 11 | -------------------------------------------------------------------------------- /web/index.php: -------------------------------------------------------------------------------- 1 | handle($request); 20 | $response->send(); 21 | 22 | $kernel->terminate($request, $response); 23 | -------------------------------------------------------------------------------- /.environment: -------------------------------------------------------------------------------- 1 | # Statements in this file will be executed (sourced) by the shell in SSH 2 | # sessions, in deploy hooks, in cron jobs, and in the application's runtime 3 | # environment. This file must be placed in the root of the application, not 4 | # necessarily the git repository's root. In case of multiple applications, 5 | # each application can have its own .environment file. 6 | 7 | # Allow executable app dependencies from Composer to be run from the path. 8 | if [ -n "$PLATFORM_APP_DIR" -a -f "$PLATFORM_APP_DIR"/composer.json ] ; then 9 | bin=$(composer config bin-dir --working-dir="$PLATFORM_APP_DIR" --no-interaction 2>/dev/null) 10 | export PATH="${PLATFORM_APP_DIR}/${bin:-vendor/bin}:${PATH}" 11 | fi 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore directories generated by Composer 2 | /drush/contrib/ 3 | /vendor/ 4 | /web/core/ 5 | /web/modules/contrib/ 6 | /web/themes/contrib/ 7 | /web/profiles/contrib/ 8 | /web/libraries/ 9 | console/ 10 | 11 | # Ignore sensitive information 12 | /web/sites/*/settings.local.php 13 | 14 | # Ignore Drupal's file directory 15 | /web/sites/*/files/ 16 | 17 | # Ignore SimpleTest multi-site environment. 18 | /web/sites/simpletest 19 | 20 | # Ignore files generated by PhpStorm 21 | /.idea/ 22 | 23 | # Ignore .env files as they are personal 24 | /.env 25 | 26 | # Ignore mounts 27 | web/sites/default/files 28 | tmp 29 | private 30 | .drush 31 | drush-backups 32 | .console 33 | /.editorconfig 34 | /.gitattributes -------------------------------------------------------------------------------- /drush/platformsh_deploy_drupal.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # We don't want to run drush commands if drupal isn't installed. 4 | # Similarly, we don't want to attempt to run config-import if there aren't any config files to import 5 | # @todo expand further to pass --uri for all sites, with an eye towards multisite 6 | # 7 | 8 | 9 | if [ -n "$(drush status --field=bootstrap)" ]; then 10 | drush -y cache-rebuild 11 | drush -y updatedb 12 | if [ -n "$(ls $(drush php:eval "echo realpath(Drupal\Core\Site\Settings::get('config_sync_directory'));")/*.yml 2>/dev/null)" ]; then 13 | drush -y config-import 14 | else 15 | echo "No config to import. Skipping." 16 | fi 17 | else 18 | echo "Drupal not installed. Skipping standard Drupal deploy steps" 19 | fi 20 | -------------------------------------------------------------------------------- /web/update.php: -------------------------------------------------------------------------------- 1 | handle($request); 28 | $response->send(); 29 | 30 | $kernel->terminate($request, $response); 31 | -------------------------------------------------------------------------------- /web/profiles/README.txt: -------------------------------------------------------------------------------- 1 | Installation profiles define additional steps that run after the base 2 | installation of Drupal is completed. They may also offer additional 3 | functionality and change the behavior of the site. 4 | 5 | WHAT TO PLACE IN THIS DIRECTORY? 6 | -------------------------------- 7 | 8 | Place downloaded and custom installation profiles in this directory. 9 | Note that installation profiles are generally provided as part of a Drupal 10 | distribution. 11 | 12 | DOWNLOAD ADDITIONAL DISTRIBUTIONS 13 | --------------------------------- 14 | 15 | Contributed distributions from the Drupal community may be downloaded at 16 | https://www.drupal.org/project/project_distribution. 17 | 18 | MULTISITE CONFIGURATION 19 | ----------------------- 20 | 21 | In multisite configurations, installation profiles found in this directory are 22 | available to all sites during their initial site installation. 23 | 24 | MORE INFORMATION 25 | ---------------- 26 | 27 | Refer to the "Installation profiles" section of the README.txt in the Drupal 28 | root directory for further information on extending Drupal with custom profiles. 29 | -------------------------------------------------------------------------------- /.lando.upstream.yml: -------------------------------------------------------------------------------- 1 | # This file sets some good defaults for local development using this Platform.sh 2 | # template with Lando. 3 | # 4 | # Note that you should not edit this file so it can continue to receive upstream 5 | # updates. If you wish to change the values below then override them in your 6 | # normal .lando.yml. 7 | 8 | # These both allow you to test this template without needing a site on Platform.sh 9 | # However you will want to replace them in your .lando.yml 10 | name: platformsh-drupal10 11 | recipe: platformsh 12 | 13 | config: 14 | 15 | # This section overrides Platform.sh configuration with values that make more 16 | # sense for local development. 17 | # 18 | # Note that "app" is the name of the application defined in your 19 | # .platform.app.yaml or applications.yaml. 20 | overrides: 21 | app: 22 | variables: 23 | drupalconfig: 24 | "system.file:path:temporary": "/tmp" 25 | drupalsettings: 26 | "skip_permissions_hardening": 1 27 | 28 | 29 | # These are tools that are commonly used during development for this template. 30 | tooling: 31 | drush: 32 | service: app 33 | -------------------------------------------------------------------------------- /web/.csslintrc: -------------------------------------------------------------------------------- 1 | --errors=box-model, 2 | display-property-grouping, 3 | duplicate-background-images, 4 | duplicate-properties, 5 | empty-rules, 6 | ids, 7 | import, 8 | important, 9 | known-properties, 10 | outline-none, 11 | overqualified-elements, 12 | qualified-headings, 13 | shorthand, 14 | star-property-hack, 15 | text-indent, 16 | underscore-property-hack, 17 | unique-headings, 18 | unqualified-attributes, 19 | vendor-prefix, 20 | zero-units 21 | --ignore=adjoining-classes, 22 | box-sizing, 23 | bulletproof-font-face, 24 | compatible-vendor-prefixes, 25 | errors, 26 | fallback-colors, 27 | floats, 28 | font-faces, 29 | font-sizes, 30 | gradients, 31 | import-ie-limit, 32 | order-alphabetical, 33 | regex-selectors, 34 | rules-count, 35 | selector-max, 36 | selector-max-approaching, 37 | selector-newline, 38 | universal-selector 39 | --exclude-list=core/assets, 40 | vendor 41 | -------------------------------------------------------------------------------- /web/themes/README.txt: -------------------------------------------------------------------------------- 1 | Themes allow you to change the look and feel of your Drupal site. You can use 2 | themes contributed by others or create your own. 3 | 4 | WHAT TO PLACE IN THIS DIRECTORY? 5 | -------------------------------- 6 | 7 | Placing downloaded and custom themes in this directory separates downloaded and 8 | custom themes from Drupal core's themes. This allows Drupal core to be updated 9 | without overwriting these files. 10 | 11 | DOWNLOAD ADDITIONAL THEMES 12 | -------------------------- 13 | 14 | Contributed themes from the Drupal community may be downloaded at 15 | https://www.drupal.org/project/project_theme. 16 | 17 | MULTISITE CONFIGURATION 18 | ----------------------- 19 | 20 | In multisite configurations, themes found in this directory are available to 21 | all sites. You may also put themes in the sites/all/themes directory, and the 22 | versions in sites/all/themes will take precedence over versions of the same 23 | themes that are here. Alternatively, the sites/your_site_name/themes directory 24 | pattern may be used to restrict themes to a specific site instance. 25 | 26 | MORE INFORMATION 27 | ----------------- 28 | 29 | Refer to the "Appearance" section of the README.txt in the Drupal root directory 30 | for further information on customizing the appearance of Drupal with custom 31 | themes. 32 | -------------------------------------------------------------------------------- /.github/workflows/project-issues.yaml: -------------------------------------------------------------------------------- 1 | ######################################################################################################################## 2 | ## ## 3 | ## This github workflow file is part of the Platform.sh process of updating and maintaining our collection of ## 4 | ## templates. For more information see https://github.com/platformsh-templates/ghrw-templates ## 5 | ## and https://github.com/search?q=topic%3Agithub-action+org%3Aplatformsh ## 6 | ## ## 7 | ## YOU CAN SAFELY DELETE THIS FILE ## 8 | ## ## 9 | ######################################################################################################################## 10 | name: Sync repository issues to template-builder project 11 | 12 | on: 13 | issues: 14 | types: 15 | - opened 16 | 17 | jobs: 18 | run-reusable-issue-sync: 19 | uses: platformsh-templates/ghrw-templates/.github/workflows/project-issues.yaml@main 20 | secrets: inherit 21 | -------------------------------------------------------------------------------- /.github/workflows/post-pr-acceptance.yaml: -------------------------------------------------------------------------------- 1 | ######################################################################################################################## 2 | ## ## 3 | ## This github workflow file is part of the Platform.sh process of updating and maintaining our collection of ## 4 | ## templates. For more information see https://github.com/platformsh-templates/ghrw-templates ## 5 | ## and https://github.com/search?q=topic%3Agithub-action+org%3Aplatformsh ## 6 | ## ## 7 | ## YOU CAN SAFELY DELETE THIS FILE ## 8 | ## ## 9 | ######################################################################################################################## 10 | name: Runs post merge-acceptance workflows 11 | on: 12 | push: 13 | branches: 14 | - main 15 | - master 16 | 17 | jobs: 18 | run-reusable-post-pr-acceptance: 19 | uses: platformsh-templates/ghrw-templates/.github/workflows/post-pr-acceptance.yaml@main 20 | secrets: inherit 21 | -------------------------------------------------------------------------------- /.github/workflows/sourceops.yaml: -------------------------------------------------------------------------------- 1 | ######################################################################################################################## 2 | ## ## 3 | ## This github workflow file is part of the Platform.sh process of updating and maintaining our collection of ## 4 | ## templates. For more information see https://github.com/platformsh-templates/ghrw-templates ## 5 | ## and https://github.com/search?q=topic%3Agithub-action+org%3Aplatformsh ## 6 | ## ## 7 | ## YOU CAN SAFELY DELETE THIS FILE ## 8 | ## ## 9 | ######################################################################################################################## 10 | name: Trigger Source Operations on a Schedule 11 | on: 12 | schedule: 13 | # Run at 00:15 every day 14 | - cron: '15 */19 * * *' 15 | workflow_dispatch: 16 | 17 | jobs: 18 | run-reusable-sop-update: 19 | uses: platformsh-templates/ghrw-templates/.github/workflows/sourceops.yaml@main 20 | secrets: inherit 21 | -------------------------------------------------------------------------------- /.github/workflows/autopr.yaml: -------------------------------------------------------------------------------- 1 | ######################################################################################################################## 2 | ## ## 3 | ## This github workflow file is part of the Platform.sh process of updating and maintaining our collection of ## 4 | ## templates. For more information see https://github.com/platformsh-templates/ghrw-templates ## 5 | ## and https://github.com/search?q=topic%3Agithub-action+org%3Aplatformsh ## 6 | ## ## 7 | ## YOU CAN SAFELY DELETE THIS FILE ## 8 | ## ## 9 | ######################################################################################################################## 10 | name: Trigger Auto PR on push to update branch 11 | on: 12 | push: 13 | branches: 14 | - update 15 | workflow_dispatch: 16 | 17 | env: 18 | PLATFORMSH_CLI_TOKEN: ${{ secrets.TEMPLATES_CLI_TOKEN }} 19 | 20 | jobs: 21 | run-reusable-autopr: 22 | uses: platformsh-templates/ghrw-templates/.github/workflows/autopr.yaml@main 23 | secrets: inherit 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/improvements.yaml: -------------------------------------------------------------------------------- 1 | name: Feature request 2 | description: For changes to improve this template. 3 | labels: 4 | - 'feature request' 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for your interest in helping improve the Platform.sh templates! 10 | Please fill in the fields below so we can understand what changes you'd like to see. 11 | 12 | - type: textarea 13 | attributes: 14 | label: What in this template can be improved or added as a feature? 15 | description: Is your feature request related to a problem? Please describe. 16 | placeholder: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 17 | validations: 18 | required: true 19 | 20 | - type: textarea 21 | attributes: 22 | label: What exactly should be updated? 23 | description: | 24 | - Share as much detail as you can to help us understand the suggestion. 25 | - What do you expect as an outcome? 26 | validations: 27 | required: true 28 | 29 | - type: textarea 30 | attributes: 31 | label: How important is this feature to you? 32 | description: Does this template lacking this feature block your work? 33 | validations: 34 | required: true 35 | 36 | - type: textarea 37 | attributes: 38 | label: Additional context 39 | description: Optionally add any other information or screenshots that could help us understand and implement the change. 40 | validations: 41 | required: false 42 | -------------------------------------------------------------------------------- /web/sites/default/settings.php: -------------------------------------------------------------------------------- 1 | inRuntime()) { 23 | return; 24 | } 25 | 26 | $routes = $platformsh->getUpstreamRoutes($platformsh->applicationName); 27 | 28 | // Sort URLs, with the primary route first, then by HTTPS before HTTP, then by length. 29 | usort($routes, function (array $a, array $b) { 30 | // false sorts before true, normally, so negate the comparison. 31 | return 32 | [!$a['primary'], strpos($a['url'], 'https://') !== 0, strlen($a['url'])] 33 | <=> 34 | [!$b['primary'], strpos($b['url'], 'https://') !== 0, strlen($b['url'])]; 35 | }); 36 | 37 | // Return the url of the first one. 38 | return reset($routes)['url'] ?: NULL; 39 | } 40 | 41 | $appRoot = dirname(__DIR__); 42 | $filename = $appRoot . '/.drush/drush.yml'; 43 | 44 | $siteUrl = _platformsh_drush_site_url(); 45 | 46 | if (empty($siteUrl)) { 47 | echo "Failed to find a site URL\n"; 48 | 49 | if (file_exists($filename)) { 50 | echo "The file exists but may be invalid: $filename\n"; 51 | } 52 | 53 | exit(1); 54 | } 55 | 56 | $siteUrlYamlEscaped = json_encode($siteUrl, JSON_UNESCAPED_SLASHES); 57 | $scriptPath = __FILE__; 58 | 59 | $success = file_put_contents($filename, <<> $GITHUB_ENV 33 | - name: 'Check and record API limits' 34 | shell: bash 35 | run: | 36 | userName=$(gh api user | jq -r '.login') 37 | currentRateLimit=$(gh api /users/platformsh/orgs -i | grep X-Ratelimit) 38 | echo "::notice::The API user ${userName} has the following X-Ratelimit values:" 39 | echo "::group::X-RateLimits for ${userName}" 40 | echo "${currentRateLimit}" 41 | echo "::endgroup::" 42 | 43 | -------------------------------------------------------------------------------- /header.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /web/sites/example.sites.php: -------------------------------------------------------------------------------- 1 | ..' => 'directory'. As an 26 | * example, to map https://www.drupal.org:8080/mysite/test to the configuration 27 | * directory sites/example.com, the array should be defined as: 28 | * @code 29 | * $sites = [ 30 | * '8080.www.drupal.org.mysite.test' => 'example.com', 31 | * ]; 32 | * @endcode 33 | * The URL, https://www.drupal.org:8080/mysite/test/, could be a symbolic link 34 | * or an Apache Alias directive that points to the Drupal root containing 35 | * index.php. An alias could also be created for a subdomain. See the 36 | * @link https://www.drupal.org/documentation/install online Drupal installation guide @endlink 37 | * for more information on setting up domains, subdomains, and subdirectories. 38 | * 39 | * The following examples look for a site configuration in sites/example.com: 40 | * @code 41 | * URL: http://dev.drupal.org 42 | * $sites['dev.drupal.org'] = 'example.com'; 43 | * 44 | * URL: http://localhost/example 45 | * $sites['localhost.example'] = 'example.com'; 46 | * 47 | * URL: http://localhost:8080/example 48 | * $sites['8080.localhost.example'] = 'example.com'; 49 | * 50 | * URL: https://www.drupal.org:8080/mysite/test/ 51 | * $sites['8080.www.drupal.org.mysite.test'] = 'example.com'; 52 | * @endcode 53 | * 54 | * @see default.settings.php 55 | * @see \Drupal\Core\DrupalKernel::getSitePath() 56 | * @see https://www.drupal.org/documentation/install/multi-site 57 | */ 58 | -------------------------------------------------------------------------------- /web/.ht.router.php: -------------------------------------------------------------------------------- 1 | = 3600' } 47 | 'The session garbage collector should be disabled in production': 48 | path: 49 | - '/.*' 50 | assertions: 51 | - { expression: 'runtime.configuration.session_gc_probability === 0' } 52 | 53 | scenarios: | 54 | #!blackfire-player 55 | 56 | name "Drupal Scenarios" 57 | 58 | group homepages 59 | visit url("/") 60 | name "Homepage (English)" 61 | expect status_code() == 200 62 | visit url("/es") 63 | name "Homepage (Español)" 64 | expect status_code() == 200 65 | 66 | group articles 67 | visit url("/en/articles") 68 | name "Articles" 69 | expect status_code() == 200 70 | 71 | group admin_anonymous 72 | visit url("/en/admin/content") 73 | expect status_code() == 403 74 | visit url("/en/admin/structure") 75 | expect status_code() == 403 76 | 77 | scenario 78 | name "Anonymous Visit" 79 | include homepages 80 | include articles 81 | include admin_anonymous 82 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yaml: -------------------------------------------------------------------------------- 1 | name: Bug report 2 | description: If you've found a problem with the template, let us know so that we can update it for everyone. 3 | labels: 4 | - 'bug' 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for your interest in helping improve the Platform.sh templates! 10 | Please fill in the fields below so we can understand what's going wrong. 11 | 12 | - type: textarea 13 | attributes: 14 | label: Describe the bug 15 | description: A clear and concise description of what the bug is. 16 | placeholder: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum eleifend diam non condimentum tincidunt. Vestibulum convallis eget ante dapibus eleifend. 17 | validations: 18 | required: true 19 | 20 | - type: textarea 21 | attributes: 22 | label: Include some logs 23 | description: Any logs you can include will help us investigate the issue. 24 | placeholder: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum eleifend diam non condimentum tincidunt. Vestibulum convallis eget ante dapibus eleifend. 25 | validations: 26 | required: true 27 | 28 | - type: textarea 29 | attributes: 30 | label: Reproducing 31 | description: Help us reproduce what you're seeing. 32 | placeholder: | 33 | Steps to reproduce the behavior: 34 | 1. Go to '...' 35 | 2. Click on '....' 36 | 3. Scroll down to '....' 37 | 4. See error 38 | validations: 39 | required: true 40 | 41 | - type: textarea 42 | attributes: 43 | label: Expected behavior 44 | description: A clear and concise description of what you expected to happen. 45 | placeholder: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum eleifend diam non condimentum tincidunt. Vestibulum convallis eget ante dapibus eleifend. 46 | validations: 47 | required: true 48 | 49 | - type: textarea 50 | attributes: 51 | label: Your environment 52 | description: Give us as many details as you can about your environment, whether that's on Platform.sh (your configuration YAMLs), or locally (your OS, services, and local development tool). 53 | placeholder: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum eleifend diam non condimentum tincidunt. Vestibulum convallis eget ante dapibus eleifend. 54 | validations: 55 | required: true 56 | 57 | - type: textarea 58 | attributes: 59 | label: Screenshots 60 | description: If applicable, add screenshots to help explain your problem. 61 | placeholder: A picture's worth a thousand words... 62 | validations: 63 | required: false 64 | 65 | - type: textarea 66 | attributes: 67 | label: Additional context 68 | description: Optionally add any other information or screenshots that could help us understand and implement the change. 69 | placeholder: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum eleifend diam non condimentum tincidunt. Vestibulum convallis eget ante dapibus eleifend. 70 | validations: 71 | required: false 72 | -------------------------------------------------------------------------------- /web/README.md: -------------------------------------------------------------------------------- 1 | Drupal Logo 2 | 3 | Drupal is an open source content management platform supporting a variety of 4 | websites ranging from personal weblogs to large community-driven websites. For 5 | more information, visit the Drupal website, [Drupal.org][Drupal.org], and join 6 | the [Drupal community][Drupal community]. 7 | 8 | ## Contributing 9 | 10 | Drupal is developed on [Drupal.org][Drupal.org], the home of the international 11 | Drupal community since 2001! 12 | 13 | [Drupal.org][Drupal.org] hosts Drupal's [GitLab repository][GitLab repository], 14 | its [issue queue][issue queue], and its [documentation][documentation]. Before 15 | you start working on code, be sure to search the [issue queue][issue queue] and 16 | create an issue if your aren't able to find an existing issue. 17 | 18 | Every issue on Drupal.org automatically creates a new community-accessible fork 19 | that you can contribute to. Learn more about the code contribution process on 20 | the [Issue forks & merge requests page][issue forks]. 21 | 22 | ## Usage 23 | 24 | For a brief introduction, see [USAGE.txt](/core/USAGE.txt). You can also find 25 | guides, API references, and more by visiting Drupal's [documentation 26 | page][documentation]. 27 | 28 | You can quickly extend Drupal's core feature set by installing any of its 29 | [thousands of free and open source modules][modules]. With Drupal and its 30 | module ecosystem, you can often build most or all of what your project needs 31 | before writing a single line of code. 32 | 33 | ## Changelog 34 | 35 | Drupal keeps detailed [change records][changelog]. You can search Drupal's 36 | changes for a record of every notable breaking change and new feature since 37 | 2011. 38 | 39 | ## Security 40 | 41 | For a list of security announcements, see the [Security advisories 42 | page][Security advisories] (available as [an RSS feed][security RSS]). This 43 | page also describes how to subscribe to these announcements via email. 44 | 45 | For information about the Drupal security process, or to find out how to report 46 | a potential security issue to the Drupal security team, see the [Security team 47 | page][security team]. 48 | 49 | ## Need a helping hand? 50 | 51 | Visit the [Support page][support] or browse [over a thousand Drupal 52 | providers][service providers] offering design, strategy, development, and 53 | hosting services. 54 | 55 | ## Legal matters 56 | 57 | Know your rights when using Drupal by reading Drupal core's 58 | [license](/core/LICENSE.txt). 59 | 60 | Learn about the [Drupal trademark and logo policy here][trademark]. 61 | 62 | [Drupal.org]: https://www.drupal.org 63 | [Drupal community]: https://www.drupal.org/community 64 | [GitLab repository]: https://git.drupalcode.org/project/drupal 65 | [issue queue]: https://www.drupal.org/project/issues/drupal 66 | [issue forks]: https://www.drupal.org/drupalorg/docs/gitlab-integration/issue-forks-merge-requests 67 | [documentation]: https://www.drupal.org/documentation 68 | [changelog]: https://www.drupal.org/list-changes/drupal 69 | [modules]: https://www.drupal.org/project/project_module 70 | [security advisories]: https://www.drupal.org/security 71 | [security RSS]: https://www.drupal.org/security/rss.xml 72 | [security team]: https://www.drupal.org/drupal-security-team 73 | [service providers]: https://www.drupal.org/drupal-services 74 | [support]: https://www.drupal.org/support 75 | [trademark]: https://www.drupal.com/trademark 76 | -------------------------------------------------------------------------------- /.ddev/providers/platform.yaml: -------------------------------------------------------------------------------- 1 | #ddev-generated 2 | # Example Platform.sh provider configuration. 3 | 4 | # To use this configuration, 5 | 6 | # 1. Check out the site from platform.sh and then configure it with `ddev config`. You'll want to use `ddev start` and make sure the basic functionality is working. 7 | # 2. Obtain and configure an API token. 8 | # a. Login to the Platform.sh Dashboard and go to Account->API Tokens to create an API token for ddev to use. 9 | # b. Add the API token to the `web_environment` section in your global ddev configuration at ~/.ddev/global_config.yaml: 10 | # ```yaml 11 | # web_environment: 12 | # - PLATFORMSH_CLI_TOKEN=abcdeyourtoken 13 | # ``` 14 | # 3. `ddev restart` 15 | # 4. Obtain your project id with `ddev exec platform`. The platform tool should show you all the information about your account and project. 16 | # 5. In your project's .ddev/providers directory, copy platform.yaml.example to platform.yaml and edit the `project_id` and `environment_name`. 17 | # 6. Run `ddev pull platform`. After you agree to the prompt, the current upstream database and files will be downloaded. 18 | # 7. Optionally use `ddev push platform` to push local files and database to platform.sh. Note that `ddev push` is a command that can potentially damage your production site, so this is not recommended. 19 | 20 | # Debugging: Use `ddev exec platform` to see what platform.sh knows about 21 | # your configuration and whether it's working correctly. 22 | 23 | environment_variables: 24 | project_id: yourproject 25 | environment: main 26 | application: drupal 27 | 28 | auth_command: 29 | command: | 30 | set -eu -o pipefail 31 | if [ -z "${PLATFORMSH_CLI_TOKEN:-}" ]; then echo "Please make sure you have set PLATFORMSH_CLI_TOKEN in ~/.ddev/global_config.yaml" && exit 1; fi 32 | 33 | db_pull_command: 34 | command: | 35 | set -x # You can enable bash debugging output by uncommenting 36 | set -eu -o pipefail 37 | ls /var/www/html/.ddev >/dev/null # This just refreshes stale NFS if possible 38 | platform db:dump --yes --gzip --file=/var/www/html/.ddev/.downloads/db.sql.gz --project="${project_id}" --environment="${environment}" --app="${application}" 39 | 40 | files_pull_command: 41 | command: | 42 | set -x # You can enable bash debugging output by uncommenting 43 | set -eu -o pipefail 44 | ls /var/www/html/.ddev >/dev/null # This just refreshes stale NFS if possible 45 | platform mount:download --yes --quiet --project="${project_id}" --environment="${environment}" --app="${application}" --mount=web/sites/default/files --target=/var/www/html/.ddev/.downloads/files 46 | 47 | 48 | # push is a dangerous command. If not absolutely needed it's better to delete these lines. 49 | db_push_command: 50 | command: | 51 | set -x # You can enable bash debugging output by uncommenting 52 | set -eu -o pipefail 53 | ls /var/www/html/.ddev >/dev/null # This just refreshes stale NFS if possible 54 | pushd /var/www/html/.ddev/.downloads >/dev/null; 55 | gzip -dc db.sql.gz | platform db:sql --project="${project_id}" --environment="${environment}" 56 | 57 | # push is a dangerous command. If not absolutely needed it's better to delete these lines. 58 | files_push_command: 59 | command: | 60 | set -x # You can enable bash debugging output by uncommenting 61 | set -eu -o pipefail 62 | ls "${DDEV_FILES_DIR}" >/dev/null # This just refreshes stale NFS if possible 63 | platform mount:upload --yes --quiet --project="${project_id}" --environment="${environment}" --source="${DDEV_FILES_DIR}" --mount=web/sites/default/files 64 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "platformsh/drupal10", 3 | "description": "This template builds Drupal 10 for Platform.sh based the \"Drupal Recommended\" Composer project.", 4 | "type": "project", 5 | "license": "GPL-2.0-or-later", 6 | "homepage": "https://www.drupal.org/project/drupal", 7 | "support": { 8 | "docs": "https://www.drupal.org/docs/user_guide/en/index.html", 9 | "chat": "https://www.drupal.org/node/314178" 10 | }, 11 | "repositories": [ 12 | { 13 | "type": "composer", 14 | "url": "https://packages.drupal.org/8" 15 | } 16 | ], 17 | "require": { 18 | "composer/installers": "^2.0", 19 | "drupal/core-composer-scaffold": "^10.0", 20 | "drupal/core-project-message": "^10.0", 21 | "drupal/core-recommended": "^10.0", 22 | "drupal/redis": "^1.6", 23 | "drush/drush": "^12", 24 | "platformsh/config-reader": "^2.4" 25 | }, 26 | "conflict": { 27 | "drupal/drupal": "*" 28 | }, 29 | "minimum-stability": "stable", 30 | "prefer-stable": true, 31 | "config": { 32 | "allow-plugins": { 33 | "composer/installers": true, 34 | "drupal/core-composer-scaffold": true, 35 | "drupal/core-project-message": true, 36 | "phpstan/extension-installer": true, 37 | "dealerdirect/phpcodesniffer-composer-installer": true, 38 | "cweagans/composer-patches": true 39 | }, 40 | "sort-packages": true 41 | }, 42 | "extra": { 43 | "drupal-scaffold": { 44 | "locations": { 45 | "web-root": "web/" 46 | } 47 | }, 48 | "installer-paths": { 49 | "web/core": [ 50 | "type:drupal-core" 51 | ], 52 | "web/libraries/{$name}": [ 53 | "type:drupal-library" 54 | ], 55 | "web/modules/contrib/{$name}": [ 56 | "type:drupal-module" 57 | ], 58 | "web/profiles/contrib/{$name}": [ 59 | "type:drupal-profile" 60 | ], 61 | "web/themes/contrib/{$name}": [ 62 | "type:drupal-theme" 63 | ], 64 | "drush/Commands/contrib/{$name}": [ 65 | "type:drupal-drush" 66 | ], 67 | "web/modules/custom/{$name}": [ 68 | "type:drupal-custom-module" 69 | ], 70 | "web/profiles/custom/{$name}": [ 71 | "type:drupal-custom-profile" 72 | ], 73 | "web/themes/custom/{$name}": [ 74 | "type:drupal-custom-theme" 75 | ] 76 | }, 77 | "drupal-core-project-message": { 78 | "include-keys": [ 79 | "homepage", 80 | "support" 81 | ], 82 | "post-create-project-cmd-message": [ 83 | " ", 84 | " Congratulations, you\u2019ve installed the Drupal codebase ", 85 | " from the drupal/recommended-project template! ", 86 | " ", 87 | "", 88 | "Next steps:", 89 | " * Install the site: https://www.drupal.org/docs/installing-drupal", 90 | " * Read the user guide: https://www.drupal.org/docs/user_guide/en/index.html", 91 | " * Get support: https://www.drupal.org/support", 92 | " * Get involved with the Drupal community:", 93 | " https://www.drupal.org/getting-involved", 94 | " * Remove the plugin that prints this message:", 95 | " composer remove drupal/core-project-message" 96 | ] 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /web/web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 13 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 39 | 48 | 49 | 52 | 61 | 62 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /.platform.app.yaml: -------------------------------------------------------------------------------- 1 | # This file describes an application. You can have multiple applications 2 | # in the same project. 3 | # 4 | # See https://docs.platform.sh/configuration/app.html 5 | 6 | # The name of this app. Must be unique within a project. 7 | name: 'drupal' 8 | 9 | # The runtime the application uses. 10 | type: 'php:8.2' 11 | 12 | dependencies: 13 | php: 14 | composer/composer: '^2.7.0' 15 | 16 | runtime: 17 | # Enable the redis extension so Drupal can communicate with the Redis cache. 18 | extensions: 19 | - redis 20 | - sodium 21 | - apcu 22 | - blackfire 23 | 24 | # The relationships of the application with services or other applications. 25 | # 26 | # The left-hand side is the name of the relationship as it will be exposed 27 | # to the application in the PLATFORM_RELATIONSHIPS variable. The right-hand 28 | # side is in the form `:`. 29 | relationships: 30 | database: 'db:mysql' 31 | redis: 'cache:redis' 32 | 33 | # The size of the persistent disk of the application (in MB). 34 | disk: 2048 35 | 36 | # The 'mounts' describe writable, persistent filesystem mounts in the application. 37 | mounts: 38 | # The default Drupal files directory. 39 | '/web/sites/default/files': 40 | source: local 41 | source_path: 'files' 42 | # Drupal gets its own dedicated tmp directory. The settings.platformsh.php 43 | # file will automatically configure Drupal to use this directory. 44 | '/tmp': 45 | source: local 46 | source_path: 'tmp' 47 | # Private file uploads are stored outside the web root. The settings.platformsh.php 48 | # file will automatically configure Drupal to use this directory. 49 | '/private': 50 | source: local 51 | source_path: 'private' 52 | # Drush needs a scratch space for its own caches. 53 | '/.drush': 54 | source: local 55 | source_path: 'drush' 56 | # Drush will try to save backups to this directory, so it must be 57 | # writeable even though you will almost never need to use it. 58 | '/drush-backups': 59 | source: local 60 | source_path: 'drush-backups' 61 | # Drupal Console will try to save backups to this directory, so it must be 62 | # writeable even though you will almost never need to use it. 63 | '/.console': 64 | source: local 65 | source_path: 'console' 66 | 67 | # Configuration of the build of this application. 68 | build: 69 | flavor: composer 70 | 71 | # The hooks executed at various points in the lifecycle of the application. 72 | hooks: 73 | # The build hook runs after Composer to finish preparing up your code. 74 | # No services are available but the disk is writeable. 75 | build: | 76 | set -e 77 | # The deploy hook runs after your application has been deployed and started. 78 | # Code cannot be modified at this point but the database is available. 79 | # The site is not accepting requests while this script runs so keep it 80 | # fast. 81 | deploy: | 82 | set -e 83 | php ./drush/platformsh_generate_drush_yml.php 84 | # if drupal is installed, will call the following drush commands: 85 | # - `cache-rebuild` 86 | # - `updatedb` 87 | # - and if config files are present, `config-import` 88 | cd web 89 | bash $PLATFORM_APP_DIR/drush/platformsh_deploy_drupal.sh 90 | 91 | # The configuration of app when it is exposed to the web. 92 | web: 93 | locations: 94 | # All requests not otherwise specified follow these rules. 95 | '/': 96 | # The folder from which to serve static assets, for this location. 97 | # 98 | # This is a filesystem path, relative to the application root. 99 | root: 'web' 100 | 101 | # How long to allow static assets from this location to be cached. 102 | # 103 | # Can be a time in seconds, or -1 for no caching. Times can be 104 | # suffixed with "s" (seconds), "m" (minutes), "h" (hours), "d" 105 | # (days), "w" (weeks), "M" (months, as 30 days) or "y" (years, as 106 | # 365 days). 107 | expires: 5m 108 | 109 | # Redirect any incoming request to Drupal's front controller. 110 | passthru: '/index.php' 111 | 112 | # Deny access to all static files, except those specifically allowed below. 113 | allow: false 114 | 115 | # Rules for specific URI patterns. 116 | rules: 117 | # Allow access to common static files. 118 | '\.(avif|webp|jpe?g|png|gif|svgz?|css|js|map|ico|bmp|eot|woff2?|otf|ttf)$': 119 | allow: true 120 | '^/robots\.txt$': 121 | allow: true 122 | '^/sitemap\.xml$': 123 | allow: true 124 | 125 | # Deny direct access to configuration files. 126 | '^/sites/sites\.php$': 127 | scripts: false 128 | '^/sites/[^/]+/settings.*?\.php$': 129 | scripts: false 130 | 131 | # The files directory has its own special configuration rules. 132 | '/sites/default/files': 133 | # Allow access to all files in the public files directory. 134 | allow: true 135 | expires: 5m 136 | passthru: '/index.php' 137 | root: 'web/sites/default/files' 138 | 139 | # Do not execute PHP scripts from the writeable mount. 140 | scripts: false 141 | 142 | rules: 143 | # Provide a longer TTL (2 weeks) for aggregated CSS and JS files. 144 | '^/sites/default/files/(css|js)': 145 | expires: 2w 146 | 147 | crons: 148 | # Run Drupal's cron tasks every 19 minutes. 149 | drupal: 150 | spec: '*/19 * * * *' 151 | commands: 152 | start: 'cd web ; drush core-cron' 153 | 154 | source: 155 | operations: 156 | auto-update: 157 | command: | 158 | curl -fsS https://raw.githubusercontent.com/platformsh/source-operations/main/setup.sh | { bash /dev/fd/3 sop-autoupdate; } 3<&0 159 | 160 | -------------------------------------------------------------------------------- /web/sites/example.settings.local.php: -------------------------------------------------------------------------------- 1 | hasRelationship('database')) { 18 | $creds = $platformsh->credentials('database'); 19 | $databases['default']['default'] = [ 20 | 'driver' => $creds['scheme'], 21 | 'database' => $creds['path'], 22 | 'username' => $creds['username'], 23 | 'password' => $creds['password'], 24 | 'host' => $creds['host'], 25 | 'port' => $creds['port'], 26 | 'pdo' => [PDO::MYSQL_ATTR_COMPRESS => !empty($creds['query']['compression'])], 27 | 'init_commands' => [ 28 | 'isolation_level' => 'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED', 29 | ], 30 | ]; 31 | } 32 | 33 | // Enable verbose error messages on development branches, but not on the production branch. 34 | // You may add more debug-centric settings here if desired to have them automatically enable 35 | // on development but not production. 36 | if (isset($platformsh->branch)) { 37 | // Production type environment. 38 | if ($platformsh->onProduction() || $platformsh->onDedicated()) { 39 | $config['system.logging']['error_level'] = 'hide'; 40 | } // Development type environment. 41 | else { 42 | $config['system.logging']['error_level'] = 'verbose'; 43 | } 44 | } 45 | 46 | // Enable Redis caching. 47 | if ($platformsh->hasRelationship('redis') && !InstallerKernel::installationAttempted() && extension_loaded('redis') && class_exists('Drupal\redis\ClientFactory')) { 48 | $redis = $platformsh->credentials('redis'); 49 | 50 | // Set Redis as the default backend for any cache bin not otherwise specified. 51 | $settings['cache']['default'] = 'cache.backend.redis'; 52 | $settings['redis.connection']['host'] = $redis['host']; 53 | $settings['redis.connection']['port'] = $redis['port']; 54 | 55 | // Apply changes to the container configuration to better leverage Redis. 56 | // This includes using Redis for the lock and flood control systems, as well 57 | // as the cache tag checksum. Alternatively, copy the contents of that file 58 | // to your project-specific services.yml file, modify as appropriate, and 59 | // remove this line. 60 | $settings['container_yamls'][] = 'modules/contrib/redis/example.services.yml'; 61 | 62 | // Allow the services to work before the Redis module itself is enabled. 63 | $settings['container_yamls'][] = 'modules/contrib/redis/redis.services.yml'; 64 | 65 | // Manually add the classloader path, this is required for the container cache bin definition below 66 | // and allows to use it without the redis module being enabled. 67 | $class_loader->addPsr4('Drupal\\redis\\', 'modules/contrib/redis/src'); 68 | 69 | // Use redis for container cache. 70 | // The container cache is used to load the container definition itself, and 71 | // thus any configuration stored in the container itself is not available 72 | // yet. These lines force the container cache to use Redis rather than the 73 | // default SQL cache. 74 | $settings['bootstrap_container_definition'] = [ 75 | 'parameters' => [], 76 | 'services' => [ 77 | 'redis.factory' => [ 78 | 'class' => 'Drupal\redis\ClientFactory', 79 | ], 80 | 'cache.backend.redis' => [ 81 | 'class' => 'Drupal\redis\Cache\CacheBackendFactory', 82 | 'arguments' => ['@redis.factory', '@cache_tags_provider.container', '@serialization.phpserialize'], 83 | ], 84 | 'cache.container' => [ 85 | 'class' => '\Drupal\redis\Cache\PhpRedis', 86 | 'factory' => ['@cache.backend.redis', 'get'], 87 | 'arguments' => ['container'], 88 | ], 89 | 'cache_tags_provider.container' => [ 90 | 'class' => 'Drupal\redis\Cache\RedisCacheTagsChecksum', 91 | 'arguments' => ['@redis.factory'], 92 | ], 93 | 'serialization.phpserialize' => [ 94 | 'class' => 'Drupal\Component\Serialization\PhpSerialize', 95 | ], 96 | ], 97 | ]; 98 | } 99 | 100 | if ($platformsh->inRuntime()) { 101 | // Configure private and temporary file paths. 102 | if (!isset($settings['file_private_path'])) { 103 | $settings['file_private_path'] = $platformsh->appDir . '/private'; 104 | } 105 | if (!isset($settings['file_temp_path'])) { 106 | $settings['file_temp_path'] = $platformsh->appDir . '/tmp'; 107 | } 108 | 109 | // Configure the default PhpStorage and Twig template cache directories. 110 | if (!isset($settings['php_storage']['default'])) { 111 | $settings['php_storage']['default']['directory'] = $settings['file_private_path']; 112 | } 113 | if (!isset($settings['php_storage']['twig'])) { 114 | $settings['php_storage']['twig']['directory'] = $settings['file_private_path']; 115 | } 116 | 117 | // Set the project-specific entropy value, used for generating one-time 118 | // keys and such. 119 | $settings['hash_salt'] = empty($settings['hash_salt']) ? $platformsh->projectEntropy : $settings['hash_salt']; 120 | 121 | // Set the deployment identifier, which is used by some Drupal cache systems. 122 | $settings['deployment_identifier'] = $settings['deployment_identifier'] ?? $platformsh->treeId; 123 | } 124 | 125 | // The 'trusted_hosts_pattern' setting allows an admin to restrict the Host header values 126 | // that are considered trusted. If an attacker sends a request with a custom-crafted Host 127 | // header then it can be an injection vector, depending on how the Host header is used. 128 | // However, Platform.sh already replaces the Host header with the route that was used to reach 129 | // Platform.sh, so it is guaranteed to be safe. The following line explicitly allows all 130 | // Host headers, as the only possible Host header is already guaranteed safe. 131 | $settings['trusted_host_patterns'] = ['.*']; 132 | 133 | // Import variables prefixed with 'drupalsettings:' into $settings 134 | // and 'drupalconfig:' into $config. 135 | foreach ($platformsh->variables() as $name => $value) { 136 | $parts = explode(':', $name); 137 | list($prefix, $key) = array_pad($parts, 3, null); 138 | switch ($prefix) { 139 | // Variables that begin with `drupalsettings` or `drupal` get mapped 140 | // to the $settings array verbatim, even if the value is an array. 141 | // For example, a variable named drupalsettings:example-setting' with 142 | // value 'foo' becomes $settings['example-setting'] = 'foo'; 143 | case 'drupalsettings': 144 | case 'drupal': 145 | $settings[$key] = $value; 146 | break; 147 | // Variables that begin with `drupalconfig` get mapped to the $config 148 | // array. Deeply nested variable names, with colon delimiters, 149 | // get mapped to deeply nested array elements. Array values 150 | // get added to the end just like a scalar. Variables without 151 | // both a config object name and property are skipped. 152 | // Example: Variable `drupalconfig:conf_file:prop` with value `foo` becomes 153 | // $config['conf_file']['prop'] = 'foo'; 154 | // Example: Variable `drupalconfig:conf_file:prop:subprop` with value `foo` becomes 155 | // $config['conf_file']['prop']['subprop'] = 'foo'; 156 | // Example: Variable `drupalconfig:conf_file:prop:subprop` with value ['foo' => 'bar'] becomes 157 | // $config['conf_file']['prop']['subprop']['foo'] = 'bar'; 158 | // Example: Variable `drupalconfig:prop` is ignored. 159 | case 'drupalconfig': 160 | if (count($parts) > 2) { 161 | $temp = &$config[$key]; 162 | foreach (array_slice($parts, 2) as $n) { 163 | $prev = &$temp; 164 | $temp = &$temp[$n]; 165 | } 166 | $prev[$n] = $value; 167 | } 168 | break; 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /web/.htaccess: -------------------------------------------------------------------------------- 1 | # 2 | # Apache/PHP/Drupal settings: 3 | # 4 | 5 | # Protect files and directories from prying eyes. 6 | 7 | 8 | Require all denied 9 | 10 | 11 | Order allow,deny 12 | 13 | 14 | 15 | # Don't show directory listings for URLs which map to a directory. 16 | Options -Indexes 17 | 18 | # Set the default handler. 19 | DirectoryIndex index.php index.html index.htm 20 | 21 | # Add correct encoding for SVGZ. 22 | AddType image/svg+xml svg svgz 23 | AddEncoding gzip svgz 24 | 25 | # Most of the following PHP settings cannot be changed at runtime. See 26 | # sites/default/default.settings.php and 27 | # Drupal\Core\DrupalKernel::bootEnvironment() for settings that can be 28 | # changed at runtime. 29 | 30 | php_value assert.active 0 31 | 32 | 33 | # Requires mod_expires to be enabled. 34 | 35 | # Enable expirations. 36 | ExpiresActive On 37 | 38 | # Cache all files and redirects for 2 weeks after access (A). 39 | ExpiresDefault A1209600 40 | 41 | 42 | # Do not allow PHP scripts to be cached unless they explicitly send cache 43 | # headers themselves. Otherwise all scripts would have to overwrite the 44 | # headers set by mod_expires if they want another caching behavior. This may 45 | # fail if an error occurs early in the bootstrap process, and it may cause 46 | # problems if a non-Drupal PHP file is installed in a subdirectory. 47 | ExpiresActive Off 48 | 49 | 50 | 51 | # Set a fallback resource if mod_rewrite is not enabled. This allows Drupal to 52 | # work without clean URLs. This requires Apache version >= 2.2.16. If Drupal is 53 | # not accessed by the top level URL (i.e.: http://example.com/drupal/ instead of 54 | # http://example.com/), the path to index.php will need to be adjusted. 55 | 56 | FallbackResource /index.php 57 | 58 | 59 | # Various rewrite rules. 60 | 61 | RewriteEngine on 62 | 63 | # Set "protossl" to "s" if we were accessed via https://. This is used later 64 | # if you enable "www." stripping or enforcement, in order to ensure that 65 | # you don't bounce between http and https. 66 | RewriteRule ^ - [E=protossl] 67 | RewriteCond %{HTTPS} on 68 | RewriteRule ^ - [E=protossl:s] 69 | 70 | # Make sure Authorization HTTP header is available to PHP 71 | # even when running as CGI or FastCGI. 72 | RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 73 | 74 | # Block access to "hidden" directories whose names begin with a period. This 75 | # includes directories used by version control systems such as Subversion or 76 | # Git to store control files. Files whose names begin with a period, as well 77 | # as the control files used by CVS, are protected by the FilesMatch directive 78 | # above. 79 | # 80 | # NOTE: This only works when mod_rewrite is loaded. Without mod_rewrite, it is 81 | # not possible to block access to entire directories from .htaccess because 82 | # is not allowed here. 83 | # 84 | # If you do not have mod_rewrite installed, you should remove these 85 | # directories from your webroot or otherwise protect them from being 86 | # downloaded. 87 | RewriteRule "/\.|^\.(?!well-known/)" - [F] 88 | 89 | # If your site can be accessed both with and without the 'www.' prefix, you 90 | # can use one of the following settings to redirect users to your preferred 91 | # URL, either WITH or WITHOUT the 'www.' prefix. Choose ONLY one option: 92 | # 93 | # To redirect all users to access the site WITH the 'www.' prefix, 94 | # (http://example.com/foo will be redirected to http://www.example.com/foo) 95 | # uncomment the following: 96 | # RewriteCond %{HTTP_HOST} . 97 | # RewriteCond %{HTTP_HOST} !^www\. [NC] 98 | # RewriteRule ^ http%{ENV:protossl}://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301] 99 | # 100 | # To redirect all users to access the site WITHOUT the 'www.' prefix, 101 | # (http://www.example.com/foo will be redirected to http://example.com/foo) 102 | # uncomment the following: 103 | # RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] 104 | # RewriteRule ^ http%{ENV:protossl}://%1%{REQUEST_URI} [L,R=301] 105 | 106 | # Modify the RewriteBase if you are using Drupal in a subdirectory or in a 107 | # VirtualDocumentRoot and the rewrite rules are not working properly. 108 | # For example if your site is at http://example.com/drupal uncomment and 109 | # modify the following line: 110 | # RewriteBase /drupal 111 | # 112 | # If your site is running in a VirtualDocumentRoot at http://example.com/, 113 | # uncomment the following line: 114 | # RewriteBase / 115 | 116 | # Redirect common PHP files to their new locations. 117 | RewriteCond %{REQUEST_URI} ^(.*)?/(install\.php) [OR] 118 | RewriteCond %{REQUEST_URI} ^(.*)?/(rebuild\.php) 119 | RewriteCond %{REQUEST_URI} !core 120 | RewriteRule ^ %1/core/%2 [L,QSA,R=301] 121 | 122 | # Rewrite install.php during installation to see if mod_rewrite is working 123 | RewriteRule ^core/install\.php core/install.php?rewrite=ok [QSA,L] 124 | 125 | # Pass all requests not referring directly to files in the filesystem to 126 | # index.php. 127 | RewriteCond %{REQUEST_FILENAME} !-f 128 | RewriteCond %{REQUEST_FILENAME} !-d 129 | RewriteCond %{REQUEST_URI} !=/favicon.ico 130 | RewriteRule ^ index.php [L] 131 | 132 | # For security reasons, deny access to other PHP files on public sites. 133 | # Note: The following URI conditions are not anchored at the start (^), 134 | # because Drupal may be located in a subdirectory. To further improve 135 | # security, you can replace '!/' with '!^/'. 136 | # Allow access to PHP files in /core (like authorize.php or install.php): 137 | RewriteCond %{REQUEST_URI} !/core/[^/]*\.php$ 138 | # Allow access to test-specific PHP files: 139 | RewriteCond %{REQUEST_URI} !/core/modules/system/tests/https?\.php 140 | # Allow access to Statistics module's custom front controller. 141 | # Copy and adapt this rule to directly execute PHP files in contributed or 142 | # custom modules or to run another PHP application in the same directory. 143 | RewriteCond %{REQUEST_URI} !/core/modules/statistics/statistics\.php$ 144 | # Deny access to any other PHP files that do not match the rules above. 145 | # Specifically, disallow autoload.php from being served directly. 146 | RewriteRule "^(.+/.*|autoload)\.php($|/)" - [F] 147 | 148 | # Rules to correctly serve gzip compressed CSS and JS files. 149 | # Requires both mod_rewrite and mod_headers to be enabled. 150 | 151 | # Serve gzip compressed CSS files if they exist and the client accepts gzip. 152 | RewriteCond %{HTTP:Accept-encoding} gzip 153 | RewriteCond %{REQUEST_FILENAME}\.gz -s 154 | RewriteRule ^(.*css_[a-zA-Z0-9-_]+)\.css$ $1\.css\.gz [QSA] 155 | 156 | # Serve gzip compressed JS files if they exist and the client accepts gzip. 157 | RewriteCond %{HTTP:Accept-encoding} gzip 158 | RewriteCond %{REQUEST_FILENAME}\.gz -s 159 | RewriteRule ^(.*js_[a-zA-Z0-9-_]+)\.js$ $1\.js\.gz [QSA] 160 | 161 | # Serve correct content types, and prevent double compression. 162 | RewriteRule \.css\.gz$ - [T=text/css,E=no-gzip:1,E=no-brotli:1] 163 | RewriteRule \.js\.gz$ - [T=text/javascript,E=no-gzip:1,E=no-brotli:1] 164 | 165 | 166 | # Serve correct encoding type. 167 | Header set Content-Encoding gzip 168 | # Force proxies to cache gzipped & non-gzipped css/js files separately. 169 | Header append Vary Accept-Encoding 170 | 171 | 172 | 173 | 174 | # Various header fixes. 175 | 176 | # Disable content sniffing, since it's an attack vector. 177 | Header always set X-Content-Type-Options nosniff 178 | # Disable Proxy header, since it's an attack vector. 179 | RequestHeader unset Proxy 180 | 181 | -------------------------------------------------------------------------------- /.ddev/config.yml: -------------------------------------------------------------------------------- 1 | type: drupal10 2 | docroot: web 3 | database: 4 | type: mariadb 5 | version: "10.4" 6 | mutagen_enabled: false 7 | use_dns_when_possible: true 8 | composer_version: "2.1" 9 | web_environment: [] 10 | php_version: "8.1" 11 | nodejs_version: "16" 12 | 13 | # Key features of ddev's config.yaml: 14 | 15 | # name: # Name of the project, automatically provides 16 | # http://projectname.ddev.site and https://projectname.ddev.site 17 | 18 | # type: # drupal6/7/8/9/10, backdrop, typo3, wordpress, php 19 | 20 | # docroot: # Relative path to the directory containing index.php. 21 | 22 | # php_version: "7.4" # PHP version to use, "5.6", "7.0", "7.1", "7.2", "7.3", "7.4", "8.0", "8.1" 23 | 24 | # You can explicitly specify the webimage but this 25 | # is not recommended, as the images are often closely tied to ddev's' behavior, 26 | # so this can break upgrades. 27 | 28 | # webimage: # nginx/php docker image. 29 | 30 | # database: 31 | # type: # mysql, mariadb 32 | # version: # database version, like "10.3" or "8.0" 33 | # Note that mariadb_version or mysql_version from v1.18 and earlier 34 | # will automatically be converted to this notation with just a "ddev config --auto" 35 | 36 | # router_http_port: # Port to be used for http (defaults to port 80) 37 | # router_https_port: # Port for https (defaults to 443) 38 | 39 | # xdebug_enabled: false # Set to true to enable xdebug and "ddev start" or "ddev restart" 40 | # Note that for most people the commands 41 | # "ddev xdebug" to enable xdebug and "ddev xdebug off" to disable it work better, 42 | # as leaving xdebug enabled all the time is a big performance hit. 43 | 44 | # xhprof_enabled: false # Set to true to enable xhprof and "ddev start" or "ddev restart" 45 | # Note that for most people the commands 46 | # "ddev xhprof" to enable xhprof and "ddev xhprof off" to disable it work better, 47 | # as leaving xhprof enabled all the time is a big performance hit. 48 | 49 | # webserver_type: nginx-fpm # or apache-fpm 50 | 51 | # timezone: Europe/Berlin 52 | # This is the timezone used in the containers and by PHP; 53 | # it can be set to any valid timezone, 54 | # see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones 55 | # For example Europe/Dublin or MST7MDT 56 | 57 | # composer_root: 58 | # Relative path to the composer root directory from the project root. This is 59 | # the directory which contains the composer.json and where all Composer related 60 | # commands are executed. 61 | 62 | # composer_version: "2" 63 | # if composer_version:"2" it will use the most recent composer v2 64 | # It can also be set to "1", to get most recent composer v1 65 | # or "" for the default v2 created at release time. 66 | # It can be set to any existing specific composer version. 67 | # After first project 'ddev start' this will not be updated until it changes 68 | 69 | # nodejs_version: "16" 70 | # change from the default system Node.js version to another supported version, like 12, 14, 17. 71 | # Note that you can use 'ddev nvm' or nvm inside the web container to provide nearly any 72 | # Node.js version, including v6, etc. 73 | 74 | # additional_hostnames: 75 | # - somename 76 | # - someothername 77 | # would provide http and https URLs for "somename.ddev.site" 78 | # and "someothername.ddev.site". 79 | 80 | # additional_fqdns: 81 | # - example.com 82 | # - sub1.example.com 83 | # would provide http and https URLs for "example.com" and "sub1.example.com" 84 | # Please take care with this because it can cause great confusion. 85 | 86 | # upload_dir: custom/upload/dir 87 | # would set the destination path for ddev import-files to /custom/upload/dir 88 | 89 | # working_dir: 90 | # web: /var/www/html 91 | # db: /home 92 | # would set the default working directory for the web and db services. 93 | # These values specify the destination directory for ddev ssh and the 94 | # directory in which commands passed into ddev exec are run. 95 | 96 | # omit_containers: [db, dba, ddev-ssh-agent] 97 | # Currently only these containers are supported. Some containers can also be 98 | # omitted globally in the ~/.ddev/global_config.yaml. Note that if you omit 99 | # the "db" container, several standard features of ddev that access the 100 | # database container will be unusable. In the global configuration it is also 101 | # possible to omit ddev-router, but not here. 102 | 103 | # nfs_mount_enabled: false 104 | # Great performance improvement but requires host configuration first. 105 | # See https://ddev.readthedocs.io/en/stable/users/performance/#using-nfs-to-mount-the-project-into-the-container 106 | 107 | # mutagen_enabled: false 108 | # Experimental performance improvement using mutagen asynchronous updates. 109 | # See https://ddev.readthedocs.io/en/latest/users/performance/#using-mutagen 110 | 111 | # fail_on_hook_fail: False 112 | # Decide whether 'ddev start' should be interrupted by a failing hook 113 | 114 | # host_https_port: "59002" 115 | # The host port binding for https can be explicitly specified. It is 116 | # dynamic unless otherwise specified. 117 | # This is not used by most people, most people use the *router* instead 118 | # of the localhost port. 119 | 120 | # host_webserver_port: "59001" 121 | # The host port binding for the ddev-webserver can be explicitly specified. It is 122 | # dynamic unless otherwise specified. 123 | # This is not used by most people, most people use the *router* instead 124 | # of the localhost port. 125 | 126 | # host_db_port: "59002" 127 | # The host port binding for the ddev-dbserver can be explicitly specified. It is dynamic 128 | # unless explicitly specified. 129 | 130 | # phpmyadmin_port: "8036" 131 | # phpmyadmin_https_port: "8037" 132 | # The PHPMyAdmin ports can be changed from the default 8036 and 8037 133 | 134 | # host_phpmyadmin_port: "8036" 135 | # The phpmyadmin (dba) port is not normally bound on the host at all, instead being routed 136 | # through ddev-router, but it can be specified and bound. 137 | 138 | # mailhog_port: "8025" 139 | # mailhog_https_port: "8026" 140 | # The MailHog ports can be changed from the default 8025 and 8026 141 | 142 | # host_mailhog_port: "8025" 143 | # The mailhog port is not normally bound on the host at all, instead being routed 144 | # through ddev-router, but it can be bound directly to localhost if specified here. 145 | 146 | # webimage_extra_packages: [php7.4-tidy, php-bcmath] 147 | # Extra Debian packages that are needed in the webimage can be added here 148 | 149 | # dbimage_extra_packages: [telnet,netcat] 150 | # Extra Debian packages that are needed in the dbimage can be added here 151 | 152 | # use_dns_when_possible: true 153 | # If the host has internet access and the domain configured can 154 | # successfully be looked up, DNS will be used for hostname resolution 155 | # instead of editing /etc/hosts 156 | # Defaults to true 157 | 158 | # project_tld: ddev.site 159 | # The top-level domain used for project URLs 160 | # The default "ddev.site" allows DNS lookup via a wildcard 161 | # If you prefer you can change this to "ddev.local" to preserve 162 | # pre-v1.9 behavior. 163 | 164 | # ngrok_args: --subdomain mysite --auth username:pass 165 | # Provide extra flags to the "ngrok http" command, see 166 | # https://ngrok.com/docs#http or run "ngrok http -h" 167 | 168 | # disable_settings_management: false 169 | # If true, ddev will not create CMS-specific settings files like 170 | # Drupal's settings.php/settings.ddev.php or TYPO3's AdditionalConfiguration.php 171 | # In this case the user must provide all such settings. 172 | 173 | # You can inject environment variables into the web container with: 174 | # web_environment: 175 | # - SOMEENV=somevalue 176 | # - SOMEOTHERENV=someothervalue 177 | 178 | # no_project_mount: false 179 | # (Experimental) If true, ddev will not mount the project into the web container; 180 | # the user is responsible for mounting it manually or via a script. 181 | # This is to enable experimentation with alternate file mounting strategies. 182 | # For advanced users only! 183 | 184 | # bind_all_interfaces: false 185 | # If true, host ports will be bound on all network interfaces, 186 | # not just the localhost interface. This means that ports 187 | # will be available on the local network if the host firewall 188 | # allows it. 189 | 190 | # Many ddev commands can be extended to run tasks before or after the 191 | # ddev command is executed, for example "post-start", "post-import-db", 192 | # "pre-composer", "post-composer" 193 | # See https://ddev.readthedocs.io/en/stable/users/extending-commands/ for more 194 | # information on the commands that can be extended and the tasks you can define 195 | # for them. Example: 196 | #hooks: 197 | # post-import-db: 198 | # - exec: drush cr 199 | # - exec: drush updb 200 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > [!WARNING] 2 | > **This repository is no longer maintained by our internal teams.** 3 | > The template is provided *as is* and will not receive updates, bug fixes, or new features. 4 | > You are welcome to contribute on it or fork the repository and modify it for your own use. 5 | > To deploy this template on [Upsun](https://www.upsun.com), you can use the command [upsun project:convert](https://docs.upsun.com/administration/cli/reference.html#projectconvert) 6 | > on this codebase to convert the existing `.platform.app.yaml` configuration file to the [Upsun Flex format](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.html). 7 | 8 |

9 | 10 | 11 | 12 |

13 | 14 |

Deploy Drupal 10 on Platform.sh

15 | 16 |

17 | Contribute, request a feature, or check out our resources 18 |
19 |
20 | Join our community       21 | Documentation       22 | Blog       23 | Report a bug       24 | Request a feature 25 |

26 |

27 | 28 |

29 | 30 | Open issues 31 |    32 | 33 | Open PRs 34 |    35 | 36 | License 37 | 38 |

39 | 40 |
41 | 42 |

43 | Contents 44 |

45 | About       46 | Getting started       47 | Migrate       48 | Learn       49 | Contribute       50 |
51 |

52 |
53 | 54 | ## About 55 | 56 | This template builds Drupal 10 using the "Drupal Recommended" Composer project. It is pre-configured to use MariaDB and Redis for caching. The Drupal installer will skip asking for database credentials as they are already provided. 57 | 58 | Drupal is a flexible and extensible PHP-based CMS framework. 59 | 60 | ### Features 61 | 62 | - PHP 8.2 63 | - MariaDB 10.11 64 | - Redis 7.2 65 | - Drush included 66 | - Automatic TLS certificates 67 | - Composer-based build 68 | 69 | 70 | ## Getting started 71 | 72 | ### Deploy 73 | 74 | #### Quickstart 75 | 76 | 77 | The quickest way to deploy this template on Platform.sh is by clicking the button below. 78 | This will automatically create a new project and initialize the repository for you. 79 | 80 | You can also quickly recreate this project locally with the following command: 81 | 82 | ```bash 83 | composer create-project platformsh/drupal10 -s dev 84 | ``` 85 | 86 | 87 | > **Note:** 88 | > 89 | > Platform.sh templates prioritize upstream release versions over our own. Despite this, we update template dependencies on a scheduled basis independent of those upstreams. Because of this, template repos do not contain releases. This may change in the future, but until then the `-s dev` flag is necessary to use `composer create-project`. 90 | 91 | 92 | 93 | #### Other deployment options 94 | 95 | For all of the other options below, clone this repository first: 96 | 97 | ```bash 98 | git clone https://github.com/platformsh-templates/drupal10 99 | ``` 100 | 101 | If you're trying to deploy from GitHub, you can generate a copy of this repository first in your own namespace by clicking the [Use this template](https://github.com/platformsh-templates/drupal10/generate) button at the top of this page. 102 | 103 | Then you can clone a copy of it locally with `git clone git@github.com:YOUR_NAMESPACE/drupal10.git`. 104 | 105 | 106 |
107 | Deploy directly to Platform.sh from the command line 108 | 110 | 111 | 1. Create a free trial: 112 | 113 | [Register for a 30 day free trial with Platform.sh](https://auth.api.platform.sh/register). When you have completed signup, select the **Create from scratch** project option. Give you project a name, and select a region where you would like it to be deployed. As for the *Production environment* option, make sure to match it to this repository's settings, or to what you have updated the default branch to locally. 114 | 115 | 1. Install the Platform.sh CLI 116 | 117 | #### Linux/OSX 118 | 119 | ```bash 120 | curl -sS https://platform.sh/cli/installer | php 121 | ``` 122 | 123 | #### Windows 124 | 125 | ```bash 126 | curl -f https://platform.sh/cli/installer -o cli-installer.php 127 | php cli-installer.php 128 | ``` 129 | 130 | You can verify the installation by logging in (`platformsh login`) and listing your projects (`platform project:list`). 131 | 132 | 1. Set the project remote 133 | 134 | Find your `PROJECT_ID` by running the command `platform project:list` 135 | 136 | ```bash 137 | +---------------+------------------------------------+------------------+---------------------------------+ 138 | | ID | Title | Region | Organization | 139 | +---------------+------------------------------------+------------------+---------------------------------+ 140 | | PROJECT_ID | Your Project Name | xx-5.platform.sh | your-username | 141 | +---------------+------------------------------------+------------------+---------------------------------+ 142 | ``` 143 | 144 | Then from within your local copy, run the command `platform project:set-remote PROJECT_ID`. 145 | 146 | 1. Push 147 | 148 | ```bash 149 | git push platform DEFAULT_BRANCH 150 | ``` 151 | 152 | 154 |
155 | 156 |
157 | Integrate with a GitHub repo and deploy pull requests 158 | 160 | 161 | 1. Create a free trial: 162 | 163 | [Register for a 30 day free trial with Platform.sh](https://auth.api.platform.sh/register). When you have completed signup, select the **Create from scratch** project option. Give you project a name, and select a region where you would like it to be deployed. As for the *Production environment* option, make sure to match it to whatever you have set at `https://YOUR_NAMESPACE/nextjs-drupal`. 164 | 165 | 1. Install the Platform.sh CLI 166 | 167 | #### Linux/OSX 168 | 169 | ```bash 170 | curl -sS https://platform.sh/cli/installer | php 171 | ``` 172 | 173 | #### Windows 174 | 175 | ```bash 176 | curl -f https://platform.sh/cli/installer -o cli-installer.php 177 | php cli-installer.php 178 | ``` 179 | 180 | You can verify the installation by logging in (`platformsh login`) and listing your projects (`platform project:list`). 181 | 182 | 1. Setup the integration: 183 | 184 | Consult the [GitHub integration documentation](https://docs.platform.sh/integrations/source/github.html#setup) to finish connecting your repository to a project on Platform.sh. You will need to create an Access token on GitHub to do so. 185 | 186 | 188 |
189 | 190 |
191 | Integrate with a GitLab repo and deploy merge requests 192 | 194 | 195 | 1. Create a free trial: 196 | 197 | [Register for a 30 day free trial with Platform.sh](https://auth.api.platform.sh/register). When you have completed signup, select the **Create from scratch** project option. Give you project a name, and select a region where you would like it to be deployed. As for the *Production environment* option, make sure to match it to this repository's settings, or to what you have updated the default branch to locally. 198 | 199 | 1. Install the Platform.sh CLI 200 | 201 | #### Linux/OSX 202 | 203 | ```bash 204 | curl -sS https://platform.sh/cli/installer | php 205 | ``` 206 | 207 | #### Windows 208 | 209 | ```bash 210 | curl -f https://platform.sh/cli/installer -o cli-installer.php 211 | php cli-installer.php 212 | ``` 213 | 214 | You can verify the installation by logging in (`platformsh login`) and listing your projects (`platform project:list`). 215 | 216 | 1. Create the repository 217 | 218 | Create a new repository on GitLab, set it as a new remote for your local copy, and push to the default branch. 219 | 220 | 1. Setup the integration: 221 | 222 | Consult the [GitLab integration documentation](https://docs.platform.sh/integrations/source/gitlab.html#setup) to finish connecting a repository to a project on Platform.sh. You will need to create an Access token on GitLab to do so. 223 | 224 | 226 |
227 | 228 |
229 | Integrate with a Bitbucket repo and deploy pull requests 230 | 232 | 233 | 1. Create a free trial: 234 | 235 | [Register for a 30 day free trial with Platform.sh](https://auth.api.platform.sh/register). When you have completed signup, select the **Create from scratch** project option. Give you project a name, and select a region where you would like it to be deployed. As for the *Production environment* option, make sure to match it to this repository's settings, or to what you have updated the default branch to locally. 236 | 237 | 1. Install the Platform.sh CLI 238 | 239 | #### Linux/OSX 240 | 241 | ```bash 242 | curl -sS https://platform.sh/cli/installer | php 243 | ``` 244 | 245 | #### Windows 246 | 247 | ```bash 248 | curl -f https://platform.sh/cli/installer -o cli-installer.php 249 | php cli-installer.php 250 | ``` 251 | 252 | You can verify the installation by logging in (`platformsh login`) and listing your projects (`platform project:list`). 253 | 254 | 1. Create the repository 255 | 256 | Create a new repository on Bitbucket, set it as a new remote for your local copy, and push to the default branch. 257 | 258 | 1. Setup the integration: 259 | 260 | Consult the [Bitbucket integration documentation](https://docs.platform.sh/integrations/source/bitbucket.html#setup) to finish connecting a repository to a project on Platform.sh. You will need to create an Access token on Bitbucket to do so. 261 | 262 | 264 |
265 | 266 | 267 | 268 | ### Post-install 269 | 270 | Run through the Drupal installer as normal. You will not be asked for database credentials as those are already provided. 271 | 272 | ### Local development 273 | 274 | This section provides instructions for running the `drupal10` template locally, connected to a live database instance on an active Platform.sh environment. 275 | 276 | In all cases for developing with Platform.sh, it's important to develop on an isolated environment - do not connect to data on your production environment when developing locally. 277 | Each of the options below assume that you have already deployed this template to Platform.sh, as well as the following starting commands: 278 | 279 | ```bash 280 | $ platform get PROJECT_ID 281 | $ cd project-name 282 | $ platform environment:branch updates 283 | ``` 284 | 285 |
286 | Drupal: using ddev
287 | 288 | ddev provides an integration with Platform.sh that makes it simple to develop Drupal locally. Check the [providers documentation](https://ddev.readthedocs.io/en/latest/users/providers/platform/) for the most up-to-date information. 289 | 290 | In general, the steps are as follows: 291 | 292 | 1. [Install ddev](https://ddev.readthedocs.io/en/stable/#installation). 293 | 1. A configuration file has already been provided at `.ddev/providers/platform.yaml`, so you should not need to run `ddev config`. 294 | 1. [Retrieve an API token](https://docs.platform.sh/development/cli/api-tokens.html#get-a-token) for your organization via the management console. 295 | 1. Update your dedev global configuration file to use the token you've just retrieved: 296 | ```yaml 297 | web_environment: 298 | - PLATFORMSH_CLI_TOKEN=abcdeyourtoken` 299 | ``` 300 | 1. Run `ddev restart`. 301 | 1. Get your project ID with `platform project:info`. If you have not already connected your local repo with the project (as is the case with a source integration, by default), you can run `platform project:list` to locate the project ID, and `platform project:set-remote PROJECT_ID` to configure Platform.sh locally. 302 | 1. Update the `.ddev/providers/platform.yaml` file for your current setup: 303 | ```yaml 304 | environment_variables: 305 | project_id: PROJECT_ID 306 | environment: CURRENT_ENVIRONMENT 307 | application: drupal 308 | ``` 309 | 1. Get the current environment's data with `ddev pull platform`. 310 | 1. When you have finished with your work, run `ddev stop` and `ddev poweroff`. 311 | 312 |
313 |
314 | Drupal: using Lando
315 | 316 | Lando supports PHP applications [configured to run on Platform.sh](https://docs.platform.sh/development/local/lando.html), and pulls from the same container registry Platform.sh uses on your remote environments during your local builds through its own [recipe and plugin](https://docs.lando.dev/platformsh/). 317 | 318 | 1. [Install Lando](https://docs.lando.dev/getting-started/installation.html). 319 | 1. Make sure Docker is already running - Lando will attempt to start Docker for you, but it's best to have it running in the background before beginning. 320 | 1. Start your apps and services with the command `lando start`. 321 | 1. To get up-to-date data from your Platform.sh environment ([services *and* mounts](https://docs.lando.dev/platformsh/sync.html#pulling)), run the command `lando pull`. 322 | 1. If at any time you have updated your Platform.sh configuration files, run the command `lando rebuild`. 323 | 1. When you have finished with your work, run `lando stop` and `lando poweroff`. 324 | 325 |
326 | 327 | 328 | 329 | > **Note:** 330 | > 331 | > For many of the steps above, you may need to include the CLI flags `-p PROJECT_ID` and `-e ENVIRONMENT_ID` if you are not in the project directory or if the environment is associated with an existing pull request. 332 | 333 | 334 | ## Migrate 335 | 336 | The steps below outline the important steps for migrating your application to Platform.sh - adding the required configuration files and dependencies, for example. 337 | Not every step will be applicable to each person's migration. 338 | These steps actually assume the earliest starting point possible - that there is no code at all locally, and that this template repository will be rebuilt completely from scratch. 339 | 340 | - [Getting started](#getting-started-1) 341 | - [Adding and updating files](#adding-and-updating-files) 342 | - [Dependencies](#dependencies) 343 | - [Deploying to Platform.sh](#deploying-to-platformsh) 344 | - [Migrating your data](#migrating-your-data) 345 | - [Next steps](#next-steps) 346 | 347 | If you already have code you'd like to migrate, feel free to focus on the steps most relevant to your application and skip the first section. 348 | 349 | ### Getting started 350 | 351 | Assuming that your starting point is no local code, the steps below will setup a starting repository we can begin to make changes to to rebuild this template and migrate to Platform.sh. 352 | If you already have a codebase you are trying to migrate, move onto the next step - [Adding and updating files](#adding-and-updating-files) - and substitute any reference to the default branch `main` with some other branch name. 353 | 354 | 355 | 356 | ```bash 357 | $ mkdir drupal10 && cd drupal10 358 | $ git init 359 | $ git remote add upstream https://github.com/drupal/recommended-project.git 360 | $ git branch -m main 361 | $ git fetch --all --depth=2 362 | $ git fetch --all --tags 363 | $ git merge --allow-unrelated-histories -X theirs 10.0.0-rc1 364 | 365 | ``` 366 | 367 | 368 | 369 | ### Adding and updating files 370 | 371 | A small number of files need to be added to or modified in your repository at this point. 372 | Some of them explicitly configure how the application is built and deployed on Platform.sh, while others simply modify files you may already have locally, in which case you will need to replicate those changes. 373 | 374 | Open the dropdown below to view all of the **Added** and **Updated** files you'll need to reproduce in your migration. 375 | 376 |
377 | View files
378 | 379 | 380 | 381 | | File | Purpose | 382 | |:-----------|:--------| 383 | | [`config/sync/.gitkeep`](config/sync/.gitkeep) | **Added** | 384 | | [`web/sites/default/settings.php`](web/sites/default/settings.php) | **Updated:**

The Drupal settings file has been updated to import and use `web/sites/default/settings.platformsh.php`. | 385 | | [`web/sites/default/settings.platformsh.php`](web/sites/default/settings.platformsh.php) | **Added:**

Contains Platform.sh-specific configuration, namely setting up the database connection to the MariaDB service and caching via Redis. | 386 | | [`.environment`](.environment) | **Added:**

The `.environment` file is a convenient place to [set environment variables](https://docs.platform.sh/development/variables/set-variables.html#set-variables-via-script) relevant to your applications that may be dependent on the current environment. It is sourced before the start command is run, as the first step in the `deploy` and `post_deploy` hooks, and at the beginning of each session when you SSH into an application container. It is written in dash, so be aware of the differences to bash.

It can be used to set any environment variable, including ones that depend on Platform.sh-provided variables like `PLATFORM_RELATIONSHIPS` and `PLATFORM_ROUTES`, or to modify `PATH`. This file should not [produce output](https://docs.platform.sh/development/variables/set-variables.html#testing-environment-scripts).

Here, the Composer config and `PATH` are updated to allow executable app dependencies from Composer to be run from the path (i.e. `drush`). | 387 | | [`.gitignore`](.gitignore) | **Added:**

A `.gitignore` file is not included in the upstream, so one has been added. | 388 | | [`.platform.app.yaml`](.platform.app.yaml) | **Added:**

This file is required to define the build and deploy process for all application containers on Platform.sh. Within this file, the runtime version, relationships to service containers, and writable mounts are configured. It's also in this file that it is defined what dependencies are installed, when they are installed, and that package manager will be used to do so.

Take a look at the [Application](https://docs.platform.sh/configuration/app.html) documentation for more details about configuration. For more information about the sequence of events that lead from a build to deployment, see the [Build and deploy timeline documentation](https://docs.platform.sh/overview/build-deploy.html).

This template uses Composer 2 to install dependencies using the default `composer` [build flavor](https://docs.platform.sh/languages/php.html#build-flavor) prior to the `build` hook. Drush tasks are run during the `deploy` hook, and referenced again during the defined `cron` job. | 389 | | [`drush/platformsh_generate_drush_yml.php`](drush/platformsh_generate_drush_yml.php) | **Added:**

This file has been included to generate the drush yaml configuration on every deployment. | 390 | | [`.platform/services.yaml`](.platform/services.yaml) | **Added:**

Platform.sh provides a number of on-demand managed services that can easily be added to your projects. It's within this file that each service's version, name, resources, and additional configuration are set. See the [Services documentation](https://docs.platform.sh/configuration/services.html) for more details on configuration, version and service availability.

In this template, MariaDB and Redis have been configured. | 391 | | [`.platform/routes.yaml`](.platform/routes.yaml) | **Added:**

This file is require to deploy on Platform.sh, as it defines how requests should be handled on the platform. It's within this file that redirects and basic caching can be configured. See the [Routes documentation](https://docs.platform.sh/configuration/routes.html) for more configuration details.

| 392 | | [`php.ini`](php.ini) | **Added:**

An initial `php.ini` file has also beed added. The settings are a result of performance testing and best practice recommendations coming from [Blackfire.io](https://blackfire.io). They will initialize Drupal with a number of good baseline performance settings for production applications, and complement many of the tests specified in [`.blackfire.yml`](.blackfire.yml). | 393 | | [`.blackfire.yml`](.blackfire.yml) | **Added:**

This file has been added to help you get started using [Blackfire.io](https://blackfire.io) on your project. See [the Blackfire section below](#blackfireio-creating-a-continuous-observability-strategy) for more information on how to get started. | 394 | | [`.lando.upstream.yml`](.lando.upstream.yml) | **Added:**

This file configures [Lando](https://docs.platform.sh/development/local/lando.html) as a local development option for this template. See the [Platform.sh Lando plugin documentation](https://docs.lando.dev/platformsh/) for more information about configuration and the [Local development](#local-development) section of this README for how to get started. | 395 | | [`.ddev/providers/platform.yaml`](.ddev/providers/platform.yaml) | **Added:**

This file configures [ddev](https://ddev.readthedocs.io/en/latest/users/providers/platform/) as a local development option for this template. See the [Platform.sh ddev integration documentation](https://ddev.readthedocs.io/en/latest/users/providers/platform/) for more information about configuration and the [Local development](#local-development) section of this README for how to get started. Be sure to follow the instructions provided through the ddev CLI and in the comments section of that file to correctly configure ddev for your project. | 396 | 397 | 398 | 399 |
400 | 401 | ### Dependencies and configuration 402 | 403 | Sometimes it is necessary to install additional dependencies to and modify the configuration of an upstream project to deploy on Platform.sh. 404 | When it is, we do our best to keep these modifications to the minimum necessary. 405 | Run the commands below to reproduce the dependencies in this template. 406 | 407 | 408 | 409 | ```bash 410 | $ composer require platformsh/config-reader drush/drush drupal/redis 411 | $ composer config allow-plugins.composer/installers true --no-plugins 412 | $ composer config allow-plugins.drupal/core-composer-scaffold true --no-plugins 413 | $ composer config allow-plugins.drupal/core-project-message true --no-plugins 414 | $ composer config allow-plugins.cweagans/composer-patches true --no-plugins 415 | 416 | ``` 417 | 418 | 419 | 420 | ### Deploying to Platform.sh 421 | 422 | Your repository now has all of the code it needs in order to deploy to Platform.sh. 423 | 424 | 425 |
426 | Deploy directly to Platform.sh from the command line 427 | 429 | 430 | 1. Create a free trial: 431 | 432 | [Register for a 30 day free trial with Platform.sh](https://auth.api.platform.sh/register). When you have completed signup, select the **Create from scratch** project option. Give you project a name, and select a region where you would like it to be deployed. As for the *Production environment* option, make sure to match it to this repository's settings, or to what you have updated the default branch to locally. 433 | 434 | 1. Install the Platform.sh CLI 435 | 436 | #### Linux/OSX 437 | 438 | ```bash 439 | curl -sS https://platform.sh/cli/installer | php 440 | ``` 441 | 442 | #### Windows 443 | 444 | ```bash 445 | curl -f https://platform.sh/cli/installer -o cli-installer.php 446 | php cli-installer.php 447 | ``` 448 | 449 | You can verify the installation by logging in (`platformsh login`) and listing your projects (`platform project:list`). 450 | 451 | 1. Set the project remote 452 | 453 | Find your `PROJECT_ID` by running the command `platform project:list` 454 | 455 | ```bash 456 | +---------------+------------------------------------+------------------+---------------------------------+ 457 | | ID | Title | Region | Organization | 458 | +---------------+------------------------------------+------------------+---------------------------------+ 459 | | PROJECT_ID | Your Project Name | xx-5.platform.sh | your-username | 460 | +---------------+------------------------------------+------------------+---------------------------------+ 461 | ``` 462 | 463 | Then from within your local copy, run the command `platform project:set-remote PROJECT_ID`. 464 | 465 | 1. Push 466 | 467 | ```bash 468 | git push platform DEFAULT_BRANCH 469 | ``` 470 | 471 | 473 |
474 | 475 |
476 | Integrate with a GitHub repo and deploy pull requests 477 | 479 | 480 | 1. Create a free trial: 481 | 482 | [Register for a 30 day free trial with Platform.sh](https://auth.api.platform.sh/register). When you have completed signup, select the **Create from scratch** project option. Give you project a name, and select a region where you would like it to be deployed. As for the *Production environment* option, make sure to match it to whatever you have set at `https://YOUR_NAMESPACE/nextjs-drupal`. 483 | 484 | 1. Install the Platform.sh CLI 485 | 486 | #### Linux/OSX 487 | 488 | ```bash 489 | curl -sS https://platform.sh/cli/installer | php 490 | ``` 491 | 492 | #### Windows 493 | 494 | ```bash 495 | curl -f https://platform.sh/cli/installer -o cli-installer.php 496 | php cli-installer.php 497 | ``` 498 | 499 | You can verify the installation by logging in (`platformsh login`) and listing your projects (`platform project:list`). 500 | 501 | 1. Setup the integration: 502 | 503 | Consult the [GitHub integration documentation](https://docs.platform.sh/integrations/source/github.html#setup) to finish connecting your repository to a project on Platform.sh. You will need to create an Access token on GitHub to do so. 504 | 505 | 507 |
508 | 509 |
510 | Integrate with a GitLab repo and deploy merge requests 511 | 513 | 514 | 1. Create a free trial: 515 | 516 | [Register for a 30 day free trial with Platform.sh](https://auth.api.platform.sh/register). When you have completed signup, select the **Create from scratch** project option. Give you project a name, and select a region where you would like it to be deployed. As for the *Production environment* option, make sure to match it to this repository's settings, or to what you have updated the default branch to locally. 517 | 518 | 1. Install the Platform.sh CLI 519 | 520 | #### Linux/OSX 521 | 522 | ```bash 523 | curl -sS https://platform.sh/cli/installer | php 524 | ``` 525 | 526 | #### Windows 527 | 528 | ```bash 529 | curl -f https://platform.sh/cli/installer -o cli-installer.php 530 | php cli-installer.php 531 | ``` 532 | 533 | You can verify the installation by logging in (`platformsh login`) and listing your projects (`platform project:list`). 534 | 535 | 1. Create the repository 536 | 537 | Create a new repository on GitLab, set it as a new remote for your local copy, and push to the default branch. 538 | 539 | 1. Setup the integration: 540 | 541 | Consult the [GitLab integration documentation](https://docs.platform.sh/integrations/source/gitlab.html#setup) to finish connecting a repository to a project on Platform.sh. You will need to create an Access token on GitLab to do so. 542 | 543 | 545 |
546 | 547 |
548 | Integrate with a Bitbucket repo and deploy pull requests 549 | 551 | 552 | 1. Create a free trial: 553 | 554 | [Register for a 30 day free trial with Platform.sh](https://auth.api.platform.sh/register). When you have completed signup, select the **Create from scratch** project option. Give you project a name, and select a region where you would like it to be deployed. As for the *Production environment* option, make sure to match it to this repository's settings, or to what you have updated the default branch to locally. 555 | 556 | 1. Install the Platform.sh CLI 557 | 558 | #### Linux/OSX 559 | 560 | ```bash 561 | curl -sS https://platform.sh/cli/installer | php 562 | ``` 563 | 564 | #### Windows 565 | 566 | ```bash 567 | curl -f https://platform.sh/cli/installer -o cli-installer.php 568 | php cli-installer.php 569 | ``` 570 | 571 | You can verify the installation by logging in (`platformsh login`) and listing your projects (`platform project:list`). 572 | 573 | 1. Create the repository 574 | 575 | Create a new repository on Bitbucket, set it as a new remote for your local copy, and push to the default branch. 576 | 577 | 1. Setup the integration: 578 | 579 | Consult the [Bitbucket integration documentation](https://docs.platform.sh/integrations/source/bitbucket.html#setup) to finish connecting a repository to a project on Platform.sh. You will need to create an Access token on Bitbucket to do so. 580 | 581 | 583 |
584 | 585 | 586 | 587 | ### Migrating your data 588 | 589 | 590 | If you are moving an existing site to Platform.sh, then in addition to code you also need to migrate your data. That means your database and your files. 591 | 592 |
593 | Importing the database
594 | 595 | First, obtain a database dump from your current site and save your dump file as `database.sql`. Then, import the database into your Platform.sh site using the CLI: 596 | 597 | ```bash 598 | platform sql -e main < database.sql 599 | ``` 600 | 601 |
602 |
603 | Importing files
604 | 605 | You first need to download your files from your current hosting environment. 606 | The easiest way is likely with rsync, but consult your old host's documentation. 607 | 608 | The `platform mount:upload` command provides a straightforward way to upload an entire directory to your site at once to a `mount` defined in a `.platform.app.yaml` file. 609 | Under the hood, it uses an SSH tunnel and rsync, so it is as efficient as possible. 610 | (There is also a `platform mount:download` command you can use to download files later.) 611 | Run the following from your local Git repository root (modifying the `--source` path if needed and setting `BRANCH_NAME` to the branch you are using). 612 | 613 | A few examples are listed below, but repeat for all directories that contain data you would like to migrate. 614 | 615 | ```bash 616 | $ platform mount:upload -e main --mount web/sites/default/files --source ./web/sites/default/files 617 | $ platform mount:upload -e main --mount private --source ./private 618 | ``` 619 | 620 | Note that `rsync` is picky about its trailing slashes, so be sure to include those. 621 | 622 |
623 | 624 | 625 | 626 | ### Next steps 627 | 628 | With your application now deployed on Platform.sh, things get more interesting. 629 | Run the command `platform environment:branch new-feature` for your project, or open a trivial pull request off of your current branch. 630 | 631 | The resulting environment is an *exact* copy of production. 632 | It contains identical infrastructure to what's been defined in your configuration files, and even includes data copied from your production environment in its services. 633 | On this isolated environment, you're free to make any changes to your application you need to, and really test how they will behave on production. 634 | 635 | After that, here are a collection of additional resources you might find interesting as you continue with your migration to Platform.sh: 636 | 637 | - [Local development](#local-development) 638 | - [Troubleshooting](#troubleshooting) 639 | - [Adding a domain and going live](https://docs.platform.sh/domains/steps.html) 640 | - [(CDN) Content Delivery Networks](https://docs.platform.sh/domains/cdn.html) 641 | - [Performance and observability with Blackfire.io](https://docs.platform.sh/integrations/observability/blackfire.html) 642 | - [Pricing](https://docs.platform.sh/overview/pricing.html) 643 | - [Security and compliance](https://docs.platform.sh/security.html) 644 | 645 | 646 | ## Learn 647 | 648 | ### Troubleshooting 649 | 650 | 651 |
652 | Accessing logs
653 | 654 | After the environment has finished its deployment, you can investigate issues that occured on startup, `deploy` and `post_deploy` hooks, and generally at runtime using the CLI. Run the command: 655 | 656 | ```bash 657 | platform ssh 658 | ``` 659 | 660 | If you are running the command outside of a local copy of the project, you will need to include the `-p` (project) and/or `-e` (environment) flags as well. 661 | Once you have connected to the container, [logs](https://docs.platform.sh/development/logs.html#container-logs) are available within `/var/log/` for you to investigate. 662 | 663 |
664 | 665 | 666 |
667 | Rebuilding cache
668 | 669 | You may run into a database error after installing Drupal on your production environment initially. 670 | To fix, SSH into the application container (`platform ssh`) and rebuild the cache using Drush: 671 | 672 | ```bash 673 | drush cache-rebuild 674 | ``` 675 | 676 |
677 | 678 | 679 |
680 | Default hash_salt behavior
681 | 682 | Drupal's [default settings set](https://github.com/drupal/drupal/blob/10.3.x/core/assets/scaffold/files/default.settings.php#L252) `hash_salt` to an empty string: 683 | 684 | ```php 685 | $settings['hash_salt'] = ''; 686 | ``` 687 | 688 | In the past, Platform.sh templates have overridden this value: 689 | 690 | ```php 691 | $settings['hash_salt'] = $settings['hash_salt'] ?? $platformsh->projectEntropy; 692 | ``` 693 | 694 | This setting was insufficient to cover some user configurations - such as those cases when an application depends on a `Null` value for `hash_salt`. 695 | 696 | Now, the setting looks like this in `settings.platformsh.php`: 697 | 698 | ```bash 699 | $settings['hash_salt'] = empty($settings['hash_salt']) ? $platformsh->projectEntropy : $settings['hash_salt']; 700 | ``` 701 | 702 | This change sets `hash_salt` to the built-in environment variable `PLATFORM_PROJECT_ENTROPY` value if the project contains the default settings OR `Null`. 703 | If your application code *depends* on an empty value, feel free to comment out that line, or reset again later in that file. 704 | 705 | Feel free to visit [`platformsh-templates/drupal9#73`](https://github.com/platformsh-templates/drupal9/pull/73) for more details on this discussion. 706 | 707 |
708 | 709 | 710 | 711 | 712 | ### Blackfire.io: creating a Continuous Observability Strategy 713 | 714 | This template includes a starting [`.blackfire.yml`](.blackfire.yml) file that can be used to enable [Application Performance Monitoring](https://blackfire.io/docs/monitoring-cookbooks/index), [Profiling](https://blackfire.io/docs/profiling-cookbooks/index), [Builds](https://blackfire.io/docs/builds-cookbooks/index) and [Performance Testing](https://blackfire.io/docs/testing-cookbooks/index) on your project. Platform.sh comes with Blackfire pre-installed on application containers, and [setting up requires minimal configuration](https://docs.platform.sh/integrations/observability/blackfire.html). 715 | 716 | * [What is Blackfire?](https://blackfire.io/docs/introduction) 717 | * [Configuring Blackfire.io on a Platform.sh project](https://docs.platform.sh/integrations/observability/blackfire.html) 718 | * [Blackfire.io Platform.sh documentation](https://blackfire.io/docs/integrations/paas/platformsh) 719 | * [Profiling Cookbooks](https://blackfire.io/docs/profiling-cookbooks/index) 720 | * [Monitoring Cookbooks](https://blackfire.io/docs/monitoring-cookbooks/index) 721 | * [Testing Cookbooks](https://blackfire.io/docs/testing-cookbooks/index) 722 | * [Using Builds](https://blackfire.io/docs/builds-cookbooks/index) 723 | * [Configuring Integrations](https://blackfire.io/docs/integrations/index) 724 | 725 | 726 | ### Resources 727 | 728 | 729 | - [Drupal](https://www.drupal.org/) 730 | - [Drupal 9 on Platform.sh](https://docs.platform.sh/guides/drupal9/deploy.html) 731 | - [Platform.sh PHP documentation](https://docs.platform.sh/languages/php.html) 732 | 733 | 734 | 735 | ### Contact 736 | 737 | This template is maintained by the Platform.sh Developer Relations team, and they will be notified of all issues and pull requests you open here. 738 | 739 | - **Community:** Share your question with the community, or see if it's already been asked on our [Community site](https://community.platform.sh). 740 | - **Discord:** If you haven't done so already, you can join Upsun's [public Discord](https://discord.gg/upsun) channels and ping the `@devrel_team` with any questions. 741 | 742 | 743 | ### About Platform.sh 744 | 745 | This template has been specifically designed to deploy on Platform.sh. 746 | 747 |
748 | What is Platform.sh?
749 | 750 | Platform.sh is a unified, secure, enterprise-grade platform for building, running and scaling web applications. We’re the leader in Fleet Ops: Everything you need to manage your fleet of websites and apps is available from the start. Because infrastructure and workflows are handled from the start, apps just work, so teams can focus on what really matters: making faster changes, collaborating confidently, and scaling responsibly. Whether managing a fleet of ten or ten thousand sites and apps, Platform.sh is the Developer- preferred solution that scales right. 751 | 752 | Our key features include: 753 | 754 | * **GitOps: Git as the source of truth** 755 | 756 | Every branch becomes a development environment, and nothing can change without a commit. 757 | 758 | * **Batteries included: Managed infrastructure** 759 | 760 | [Simple abstraction in YAML](https://docs.platform.sh/configuration/yaml.html) for [committing and configuring infrastructure](https://docs.platform.sh/overview/structure.html), fully managed patch updates, and 24 [runtimes](https://docs.platform.sh/languages.html) & [services](https://docs.platform.sh/configuration/services.html) that can be added with a single line of code. 761 | 762 | * **Instant cloning: Branch, merge, repeat** 763 | 764 | [Reusable builds](https://docs.platform.sh/overview/build-deploy.html) and automatically inherited production data provide true staging environments - experiment in isolation, test, then destroy or merge. 765 | 766 | * **FleetOps: Fleet management platform** 767 | 768 | Leverage our public API along with custom tools like [Source Operations](https://docs.platform.sh/configuration/app/source-operations.html) and [Activity Scripts](https://docs.platform.sh/integrations/activity.html) to [manage thousands of applications](https://youtu.be/MILHG9OqhmE) - their dependency updates, fresh content, and upstream code. 769 | 770 | 771 | To find out more, check out the demo below and go to our [website](https://platform.sh/product/). 772 | 773 |
774 |

775 | The Platform.sh demo 776 |

777 | 778 | 779 |
780 | 781 | 782 | 783 | ## Contribute 784 | 785 |

Help us keep top-notch templates!

786 | 787 | Every one of our templates is open source, and they're important resources for users trying to deploy to Platform.sh for the first time or better understand the platform. They act as getting started guides, but also contain a number of helpful tips and best practices when working with certain languages and frameworks. 788 | 789 | See something that's wrong with this template that needs to be fixed? Something in the documentation unclear or missing? Let us know! 790 | 791 |

792 | How to contribute 793 |

794 | Report a bug       795 | Submit a feature request       796 | Open a pull request       797 |
798 |

799 |
800 |

801 | Need help? 802 |

803 | Ask the Platform.sh Community       804 | Join us on Discord       805 |
806 |

807 |
808 |

Thanks to all of our amazing contributors!

809 |
810 |

811 | 812 | 813 | 814 |

815 | 816 |

817 | Made with contrib.rocks 818 |

819 | 820 |
821 | --------------------------------------------------------------------------------