├── .cs
├── .php_cs.php
├── cs_ruleset.xml
└── md_ruleset.xml
├── .github
├── FUNDING.yml
├── PULL_REQUEST_TEMPLATE.md
├── issue_template.md
└── workflows
│ ├── main-ci.yaml
│ └── release.yaml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
├── README.md
├── bin
├── ez
└── ez-prod
├── box.json
├── composer.json
├── composer.lock
├── config
├── commands.yml
└── services.yml
├── docs
├── CHANGELOG.md
├── LEMP_architecture.puml
├── css
│ └── ezlaunchpad.css
├── ez.phar
├── ez.phar.pubkey
├── images
│ └── puml
│ │ ├── LAMP_architecture.png
│ │ └── LEMP_architecture.png
├── index.html
├── install.bash
├── install_curl.bash
├── install_wget.bash
├── installer
└── js
│ ├── clipboard.min.js
│ └── ezlaunchpad.js
├── payload
├── README.md
├── dev
│ ├── docker-compose-osx.yml
│ ├── docker-compose.yml
│ ├── engine
│ │ ├── Dockerfile
│ │ ├── entrypoint.bash
│ │ ├── php.ini
│ │ └── xdebug.ini
│ ├── nginx
│ │ ├── entrypoint.bash
│ │ ├── nginx.conf
│ │ └── nginx_v2.conf
│ ├── solr
│ │ └── entrypoint.bash
│ └── varnish
│ │ └── varnish.vcl
└── recipes
│ ├── composer_install.bash
│ ├── create_dump.bash
│ ├── ez_create.bash
│ ├── ez_install.bash
│ ├── ez_install_solr.bash
│ ├── ibexa_install.bash
│ └── import_dump.bash
├── scripts
├── buildbox.bash
├── codechecker.bash
├── functions
├── pumltoimages.bash
├── runtests.bash
└── travis_deploy.bash
├── src
├── Command
│ ├── Docker
│ │ ├── Build.php
│ │ ├── Clean.php
│ │ ├── ComposerRun.php
│ │ ├── Create.php
│ │ ├── DumpData.php
│ │ ├── Enter.php
│ │ ├── ImportData.php
│ │ ├── Initialize.php
│ │ ├── InitializeSkeleton.php
│ │ ├── Logs.php
│ │ ├── Restart.php
│ │ ├── Start.php
│ │ ├── Status.php
│ │ ├── Stop.php
│ │ ├── SymfonyRun.php
│ │ ├── Up.php
│ │ └── Update.php
│ ├── Platformsh
│ │ ├── Deploy.php
│ │ └── Setup.php
│ └── SelfUpdate.php
├── Configuration
│ ├── Configuration.php
│ └── Project.php
├── Console
│ ├── Application.php
│ └── ApplicationFactory.php
├── Core
│ ├── Client
│ │ └── Docker.php
│ ├── Command.php
│ ├── DockerCommand.php
│ ├── DockerCompose.php
│ ├── OSX
│ │ └── Optimizer
│ │ │ ├── D4M.php
│ │ │ ├── NFSAwareInterface.php
│ │ │ ├── NFSTrait.php
│ │ │ ├── NFSVolumes.php
│ │ │ ├── Optimizer.php
│ │ │ └── OptimizerInterface.php
│ ├── ProcessRunner.php
│ ├── ProjectStatusDumper.php
│ ├── ProjectWizard.php
│ └── TaskExecutor.php
├── DependencyInjection
│ └── CommandPass.php
├── Listener
│ ├── ApplicationUpdate.php
│ ├── CommandException.php
│ ├── CommandStart.php
│ ├── CommandTerminate.php
│ └── OSXListener.php
├── bootstrap.php
└── functions.php
└── tests
├── Tests
├── Behat
│ └── Commands
│ │ ├── Context.php
│ │ └── features
│ │ └── test.feature
├── Command
│ ├── Test.php
│ └── TestDockerClient.php
└── Unit
│ ├── BehatTest.php
│ ├── ConfigurationTest.php
│ ├── DockerClientTest.php
│ ├── DockerComposeTest.php
│ ├── ProjectConfigurationTest.php
│ ├── RequiredFilesTest.php
│ ├── TaskExecutorTest.php
│ └── TestCase.php
├── behat.yml
├── bootstrap.php
├── phpunit.xml.dist
└── postman
├── collection-1x.json
└── collection-2x.json
/.cs/.php_cs.php:
--------------------------------------------------------------------------------
1 | in('src');//->in('tests');
10 |
11 | return PhpCsFixer\Config::create()
12 | ->setRules(
13 | [
14 | '@Symfony' => true,
15 | 'binary_operator_spaces' => [
16 | 'align_equals' => false,
17 | 'align_double_arrow' => false,
18 | ],
19 | 'array_syntax' => ['syntax' => 'short'],
20 | 'pre_increment' => false,
21 | 'ordered_imports' => true,
22 | 'phpdoc_order' => true,
23 | 'linebreak_after_opening_tag' => true,
24 | 'phpdoc_no_package' => false,
25 | 'phpdoc_inline_tag' => false,
26 | 'cast_spaces' => false,
27 | 'no_superfluous_phpdoc_tags' => true,
28 | ]
29 | )
30 | ->setFinder($finder);
31 |
--------------------------------------------------------------------------------
/.cs/cs_ruleset.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | eZ Launchpad coding standard.
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/.cs/md_ruleset.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 | eZ Launchpad Configuration
8 |
9 |
10 | 1
11 |
12 |
13 |
14 |
15 |
16 | 1
17 |
18 |
19 |
20 |
21 |
22 | 1
23 |
24 |
25 |
26 |
27 |
28 | 1
29 |
30 |
31 |
32 |
33 |
34 | 1
35 |
36 |
37 |
38 |
39 |
40 | 1
41 |
42 |
43 |
44 |
45 |
46 | 1
47 |
48 |
49 |
50 |
51 |
52 | 1
53 |
54 |
55 |
56 |
57 |
58 | 1
59 |
60 |
61 |
62 |
63 |
64 | 1
65 |
66 |
67 |
68 |
69 |
70 | 1
71 |
72 |
73 |
74 |
75 |
76 | 1
77 |
78 |
79 |
80 |
81 |
82 | 1
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: [plopix]
2 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | | Q | A
2 | | ------------- | ---
3 | | Branch? | master / x.y.z
4 | | Bug fix? | yes/no
5 | | New feature? | yes/no
6 | | BC breaks? | yes/no
7 | | Fixed tickets | #...
8 |
9 |
16 |
--------------------------------------------------------------------------------
/.github/issue_template.md:
--------------------------------------------------------------------------------
1 | | Q | A
2 | | ---------------- | -----
3 | | Bug report? | yes/no
4 | | Feature request? | yes/no
5 | | BC Break report? | yes/no
6 | | RFC? | yes/no
7 | | Version | x.y.z
8 | | Environment | Linux/Mac/Windows
9 |
10 |
11 |
15 |
--------------------------------------------------------------------------------
/.github/workflows/main-ci.yaml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 |
7 | lint:
8 | name: Coding Standard
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/checkout@v1
12 | - name: Setup PHP
13 | uses: shivammathur/setup-php@master
14 | with:
15 | php-version: 7.4
16 | id: php
17 | - name: Install dependencies
18 | run: composer install --prefer-dist --no-progress --no-suggest --no-interaction
19 | - name: Check Sources
20 | run: php vendor/bin/phpcs --standard=.cs/cs_ruleset.xml --extensions=php src/
21 | - name: Check Tests
22 | run: php vendor/bin/phpcs --standard=.cs/cs_ruleset.xml --extensions=php src/
23 |
24 | tests:
25 | name: Tests
26 | runs-on: ubuntu-latest
27 | strategy:
28 | matrix:
29 | php: [7.3, 7.4, 8.0]
30 | steps:
31 | - uses: actions/checkout@v1
32 | - name: Setup PHP
33 | uses: shivammathur/setup-php@master
34 | with:
35 | php-version: ${{ matrix.php }}
36 | id: php
37 | - name: Validate composer.json and composer.lock
38 | run: composer validate
39 | - name: Install dependencies
40 | run: composer install --prefer-dist --no-progress --no-suggest --no-interaction
41 | - name: Show Versions
42 | run: composer info -i
43 | - name: PHP Unit
44 | run: php vendor/bin/phpunit -c tests/ --exclude-group behat
45 | - name: Behat
46 | run: php vendor/behat/behat/bin/behat -c tests/behat.yml
47 |
48 |
49 | ezplatform:
50 | name: eZ Platform
51 | runs-on: ubuntu-latest
52 | strategy:
53 | matrix:
54 | php: [7.3, 7.4, 8.0]
55 | ezversion: [2.*, 3.*]
56 | collection: [collection-2x.json]
57 | steps:
58 | - uses: actions/checkout@v1
59 | - name: Setup PHP
60 | uses: shivammathur/setup-php@master
61 | with:
62 | php-version: ${{ matrix.php }}
63 | id: php
64 | - name: Install dependencies
65 | run: composer install --prefer-dist --no-progress --no-suggest --no-interaction
66 | - name: Initialization
67 | run: php bin/ez-prod init ezsystems/ezplatform ${{ matrix.ezversion }} --no-interaction -vvv
68 | - name: Status Info
69 | run: php bin/ez-prod ps
70 | - name: Verification using Postman
71 | run:
72 | docker run --net=host -v $(pwd)/tests/postman:/etc/newman -t postman/newman run ${{ matrix.collection }}
73 |
74 | ibexa:
75 | name: Ibexa
76 | runs-on: ubuntu-latest
77 | strategy:
78 | matrix:
79 | php: [7.4, 8.0]
80 | ezversion: [3.*]
81 | collection: [collection-2x.json]
82 | steps:
83 | - uses: actions/checkout@v1
84 | - name: Setup PHP
85 | uses: shivammathur/setup-php@master
86 | with:
87 | php-version: ${{ matrix.php }}
88 | id: php
89 | - name: Install dependencies
90 | run: composer install --prefer-dist --no-progress --no-suggest --no-interaction
91 | - name: Initialization
92 | run: php bin/ez-prod init ibexa/oss ${{ matrix.ezversion }} --no-interaction -vvv
93 | - name: Status Info
94 | run: php bin/ez-prod ps
95 | - name: Verification using Postman
96 | run: docker run --net=host -v $(pwd)/tests/postman:/etc/newman -t postman/newman run ${{ matrix.collection }}
97 |
--------------------------------------------------------------------------------
/.github/workflows/release.yaml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | tags:
4 | - 'v*'
5 |
6 | name: Upload Phar
7 |
8 | jobs:
9 | build:
10 | name: Upload Phar
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/checkout@master
14 | - name: Install PROD dependencies ONLY
15 | run: composer install --prefer-dist --no-progress --no-suggest --no-interaction --no-dev
16 | - name: Build project
17 | env:
18 | EZ_LAUNCHPAD_PHAR_PRIVATE_KEY: ${{ secrets.EZ_LAUNCHPAD_PHAR_PRIVATE_KEY }}
19 | run: |
20 | echo "${EZ_LAUNCHPAD_PHAR_PRIVATE_KEY}" > ezlaunchpad-private.pem
21 | ulimit -Sn 4096
22 | curl -LSs https://box-project.github.io/box2/installer.php | php
23 | chmod 755 box.phar
24 | php -d "phar.readonly=false" ./box.phar build -vv
25 | rm ezlaunchpad-private.pem
26 |
27 | - name: Create Release
28 | id: create_release
29 | uses: actions/create-release@v1.0.0
30 | env:
31 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
32 | with:
33 | tag_name: ${{ github.ref }}
34 | release_name: Release ${{ github.ref }}
35 | draft: false
36 | prerelease: false
37 |
38 | - name: Upload Release Asset
39 | id: upload-release-asset
40 | uses: actions/upload-release-asset@v1.0.1
41 | env:
42 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
43 | with:
44 | upload_url: ${{ steps.create_release.outputs.upload_url }}
45 | asset_path: ./ez.phar
46 | asset_name: ez.phar
47 | asset_content_type: application/octet-stream
48 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /composer.phar
2 | /box.phar
3 | /ez.phar
4 | /ez.phar.*
5 | /vendor/
6 | .php~
7 | .idea
8 | .DS_Store
9 | *~
10 | *.bak
11 | ._*
12 | ~*
13 | .php_cs.cache
14 |
15 | tests/coverage
16 | tests/.phpunit.result.cache
17 |
18 | # Auto-update
19 | /docs/ez-old.phar
20 |
21 | # Tests
22 | /provisioning
23 | /ezplatform
24 | /.ezlaunchpad.yml
25 |
26 | # CI stuff
27 | /build-key.pem
28 | /ezlaunchpad-private.pem
29 | /secrets.tar
30 | /plantuml.jar
31 |
32 | # others
33 | /provisioning2ouf
34 | /provisioning2
35 | /data
36 |
37 | # we do not want that at the root (usually generated when developing eZ Launchpad)
38 | /ez_install.bash
39 | /composer_install.bash
40 | /ez_install_solr.bash
41 |
42 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # eZ Launchpad
2 |
3 | This code of conduct outlines our expectations for participants within community. Anyone who violates this code of conduct may be banned from contributing here.
4 |
5 | ## Contributor Code of Conduct
6 |
7 | ### Our Pledge
8 |
9 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
10 |
11 | ### Our Standards
12 |
13 | Examples of behavior that contributes to creating a positive environment include:
14 |
15 | - Using welcoming and inclusive language
16 | - Being respectful of differing viewpoints and experiences
17 | - Gracefully accepting constructive criticism
18 | - Focusing on what is best for the community
19 | - Showing empathy towards other community members
20 |
21 | Examples of unacceptable behavior by participants include:
22 |
23 | - The use of sexualized language or imagery and unwelcome sexual attention or advances
24 | - Trolling, insulting/derogatory comments, and personal or political attacks
25 | - Public or private harassment
26 | - Publishing others' private information, such as a physical or electronic address, without explicit permission
27 | - Other conduct which could reasonably be considered inappropriate in a professional setting
28 |
29 | ### Our Responsibilities
30 |
31 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
32 |
33 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
34 |
35 | ### Scope
36 |
37 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
38 |
39 | ### Enforcement
40 |
41 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at info@ez.no. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
42 |
43 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
44 |
45 | ### Attribution
46 |
47 | This Code of Conduct is adapted from the Contributor Covenant, version 1.4, available at http://contributor-covenant.org/version/1/4.
48 |
49 | ## Contributing
50 |
51 | [CONTRIBUTING](CONTRIBUTING.md)
52 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # eZ Launchpad
2 |
3 | ## Contribution
4 |
5 | This project comes with Coding Standards and Tests.
6 | To help you contribute a Makefile is available to simplify the actions.
7 |
8 | ```bash
9 | $ make
10 | eZ Launchpad available targets:
11 | codeclean > run the codechecker
12 | tests > run the tests
13 | coverage > generate the code coverage
14 | install > install vendors
15 | clean > removes the vendors, caches, etc.
16 | phar > build the phar locally into your home
17 | ```
18 |
19 | Please comply with `make codeclean` and `make tests` before to push, your PR won't be merged otherwise.
20 |
21 | > Note: the real *signed* .phar is generated on Travis and made available for all on Github after each merge on master.
22 | > Then there is no reason when you contribute to commit the .phar, it will be overriden at the merge.
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (C) eZ Systems AS. All rights reserved.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # === eZ Launchpad Helper ===
2 |
3 | # Styles
4 | YELLOW=$(shell echo "\033[00;33m")
5 | RED=$(shell echo "\033[00;31m")
6 | RESTORE=$(shell echo "\033[0m")
7 |
8 | # Variables
9 | PHP_BIN := php
10 | COMPOSER_BIN := composer.phar
11 | DOCKER_BIN := docker
12 | SRCS := src
13 | CURRENT_DIR := $(shell pwd)
14 | SCRIPS_DIR := $(CURRENT_DIR)/scripts
15 |
16 | .DEFAULT_GOAL := list
17 |
18 | .PHONY: list
19 | list:
20 | @echo "******************************"
21 | @echo "${YELLOW}eZ Launchpad available targets${RESTORE}:"
22 | @grep -E '^[a-zA-Z-]+:.*?## .*$$' Makefile | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " ${YELLOW}%-15s${RESTORE} > %s\n", $$1, $$2}'
23 | @echo "${RED}==============================${RESTORE}"
24 |
25 | .PHONY: install
26 | install: ## Install the vendor
27 | @composer install
28 |
29 | .PHONY: codeclean
30 | codeclean: ## Run the codechecker
31 | bash $(SCRIPS_DIR)/codechecker.bash
32 |
33 | .PHONY: tests
34 | tests: ## Run the tests
35 | bash $(SCRIPS_DIR)/runtests.bash
36 |
37 | .PHONY: behat
38 | behat: ## Run the Behat tests only
39 | bash $(SCRIPS_DIR)/runtests.bash behat
40 |
41 | .PHONY: unit
42 | unit: ## Run the Unit tests only
43 | bash $(SCRIPS_DIR)/runtests.bash unit
44 |
45 | .PHONY: convertpuml
46 | convertpuml: ## Convert PUML diagram in images
47 | bash $(SCRIPS_DIR)/pumltoimages.bash
48 |
49 | .PHONY: docs
50 | docs: ## Generate the documentation
51 | $(PHP_BIN) bin/gendocs
52 |
53 | .PHONY: phar
54 | phar: ## Build the box locally (bypass the PROD)
55 | bash $(SCRIPS_DIR)/buildbox.bash
56 |
57 | .PHONY: coverage
58 | coverage: ## Generate the code coverage
59 | rm -rf tests/coverage
60 | $(DOCKER_BIN) run -t --rm -w /app -v $(CURRENT_DIR):/app phpunit/phpunit:5.7.12 -c tests/ --coverage-html /app/tests/coverage
61 |
62 | .PHONY: clean
63 | clean: ## Removes the vendors, and caches
64 | rm -rf tests/coverage
65 | rm -f .php_cs.cache
66 | rm -f .ezlaunchpad.yml
67 | rm -rf vendor
68 | rm -rf ezplatform
69 | rm -rf provisioning
70 | rm -rf provisioning2ouf
71 | rm -f ezinstall.bash
72 |
73 |
74 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # eZ Launchpad
2 |
3 | eZ Launchpad is a CLI tool to start an eZ Platform project in 5 min on top of a full Docker stack.
4 |
5 | It's brought to you by, and supported by the eZ Community _(on ezcommunity.slack.com #ez-launchpad)_.
6 |
7 | You can find the full documentation here: https://ezsystems.github.io/launchpad
8 |
9 | | Branch | Travis build status |
10 | |:--------:|:-------------------:|
11 | | master | [](https://travis-ci.org/ezsystems/launchpad)
12 |
13 | ## Contribution
14 |
15 | [CONTRIBUTING](CONTRIBUTING.md)
16 |
17 | ## License
18 |
19 | This project is under the MIT license. See the complete license in the file:
20 |
21 | [LICENSE](LICENSE)
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/bin/ez:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | run();
17 |
--------------------------------------------------------------------------------
/bin/ez-prod:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | run();
17 |
--------------------------------------------------------------------------------
/box.json:
--------------------------------------------------------------------------------
1 | {
2 | "algorithm": "OPENSSL",
3 | "alias": "ez.phar",
4 | "banner": "eZ Launchpad",
5 | "chmod": "0755",
6 | "compression": "GZ",
7 | "compactors": [
8 | "Herrera\\Box\\Compactor\\Json",
9 | "Herrera\\Box\\Compactor\\Php"
10 | ],
11 | "directories": [
12 | "src",
13 | "config",
14 | "payload"
15 | ],
16 | "files": [
17 | "LICENSE"
18 | ],
19 | "finder": [
20 | {
21 | "name": "*.php",
22 | "exclude": [
23 | "tests",
24 | "Tests"
25 | ],
26 | "in": "vendor"
27 | }
28 | ],
29 | "git-tag": "package_version",
30 | "main": "bin/ez-prod",
31 | "key": "ezlaunchpad-private.pem",
32 | "output": "ez.phar",
33 | "stub": true
34 | }
35 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ezsystems/launchpad",
3 | "description": "eZ Launchpad - Ultimate eZ Platform CLI Helper.",
4 | "homepage": "https://github.com/ezsystems/launchpad",
5 | "require": {
6 | "php": "^7.2.5",
7 | "symfony/console": "^5.1",
8 | "symfony/yaml": "^5.1",
9 | "symfony/dependency-injection": "^5.1",
10 | "symfony/process": "^5.1",
11 | "symfony/finder": "^5.1",
12 | "symfony/config": "^5.1",
13 | "symfony/filesystem": "^5.1",
14 | "novactive/collection": "^1.1.0",
15 | "symfony/options-resolver": "^5.1",
16 | "symfony/event-dispatcher": "^5.1",
17 | "nesbot/carbon": "^2"
18 | },
19 | "require-dev": {
20 | "symfony/var-dumper": "^5.1",
21 | "friendsofphp/php-cs-fixer": "^2.14",
22 | "phpmd/phpmd": "^2.6",
23 | "squizlabs/php_codesniffer": "^3.4",
24 | "phpunit/phpunit": "^8",
25 | "behat/behat": "^3.7",
26 | "mikey179/vfsstream": "^1.6",
27 | "twig/twig": "^3",
28 | "symfony/translation": "^5.1",
29 | "symfony/twig-bridge": "^5.1"
30 | },
31 | "config": {
32 | "platform": {
33 | "php": "7.2.5"
34 | }
35 | },
36 | "autoload": {
37 | "psr-4": {
38 | "eZ\\Launchpad\\": "src/"
39 | },
40 | "files": [
41 | "src/functions.php"
42 | ]
43 | },
44 | "prefer-stable": true,
45 | "autoload-dev": {
46 | "psr-4": {
47 | "eZ\\Launchpad\\Tests\\": "tests/Tests"
48 | }
49 | },
50 | "bin": [
51 | "bin/ez"
52 | ]
53 | }
54 |
--------------------------------------------------------------------------------
/config/commands.yml:
--------------------------------------------------------------------------------
1 | ---
2 | services:
3 |
4 | _defaults:
5 | autowire: true
6 | public: true
7 |
8 | _instanceof:
9 | eZ\Launchpad\Core\Command:
10 | tags: [ezlaunchpad.command]
11 |
12 | # Not working in a Phar (method glob() is used but it is not working in a phar)
13 | #eZ\Launchpad\Command\:
14 | # resource: ../src/Command/*
15 |
16 | # then we need to list them manually
17 | eZ\Launchpad\Command\Rollback: ~
18 | eZ\Launchpad\Command\Docker\Start: ~
19 | eZ\Launchpad\Command\Docker\Stop: ~
20 | eZ\Launchpad\Command\Docker\Up: ~
21 | eZ\Launchpad\Command\Docker\Clean: ~
22 | eZ\Launchpad\Command\Docker\Status: ~
23 | eZ\Launchpad\Command\Docker\Enter: ~
24 | eZ\Launchpad\Command\Docker\Logs: ~
25 | eZ\Launchpad\Command\Docker\SymfonyRun: ~
26 | eZ\Launchpad\Command\Docker\ComposerRun: ~
27 | eZ\Launchpad\Command\Platformsh\Deploy: ~
28 |
29 | # Self
30 | eZ\Launchpad\Command\SelfUpdate:
31 | calls:
32 | - [setParameters, [ {release_url: "%github_release_url%"} ] ]
33 |
34 | # Docker
35 | eZ\Launchpad\Command\Docker\Update:
36 | calls:
37 | - [setRequiredRecipes, [ [ 'composer_install' ] ] ]
38 |
39 | eZ\Launchpad\Command\Docker\Build:
40 | calls:
41 | - [setRequiredRecipes, [ [ 'composer_install' ] ] ]
42 |
43 | eZ\Launchpad\Command\Docker\Initialize:
44 | calls:
45 | - [setRequiredRecipes, [ [ 'composer_install', 'ez_install', 'ibexa_install', 'ez_install_solr' ] ] ]
46 |
47 | eZ\Launchpad\Command\Docker\InitializeSkeleton:
48 | calls:
49 | - [setRequiredRecipes, [ [ 'composer_install' ] ] ]
50 |
51 | eZ\Launchpad\Command\Docker\Create:
52 | calls:
53 | - [setRequiredRecipes, [ [ 'composer_install', 'ez_create', 'import_dump', 'ez_install_solr' ] ] ]
54 |
55 | eZ\Launchpad\Command\Docker\DumpData:
56 | calls:
57 | - [setRequiredRecipes, [ [ 'create_dump' ] ] ]
58 |
59 | eZ\Launchpad\Command\Docker\ImportData:
60 | calls:
61 | - [setRequiredRecipes, [ [ 'import_dump' ] ] ]
62 |
63 | # Platform.sh
64 | eZ\Launchpad\Command\Platformsh\Setup:
65 | calls:
66 | - [setRequiredRecipes, [ [ 'create_dump' ] ] ]
67 |
--------------------------------------------------------------------------------
/config/services.yml:
--------------------------------------------------------------------------------
1 | ---
2 | parameters:
3 | github_release_url: "https://api.github.com/repos/ezsystems/launchpad/releases?draft=false&prerelease=false"
4 |
5 | services:
6 |
7 | _defaults:
8 | autowire: true
9 | public: true
10 |
11 | eZ\Launchpad\Listener\ApplicationUpdate:
12 | arguments:
13 | - {release_url: "%github_release_url%"}
14 | tags:
15 | - { name: kernel.event_listener, event: console.command, method: onCommandAction }
16 |
17 | eZ\Launchpad\Listener\CommandException:
18 | tags:
19 | - { name: kernel.event_listener, event: console.error, method: onExceptionAction }
20 |
21 | eZ\Launchpad\Listener\CommandStart:
22 | tags:
23 | - { name: kernel.event_listener, event: console.command, method: onCommandAction }
24 |
25 |
26 | eZ\Launchpad\Listener\CommandTerminate:
27 | tags:
28 | - { name: kernel.event_listener, event: console.terminate, method: onTerminateAction }
29 |
30 | eZ\Launchpad\Core\ProjectStatusDumper: ~
31 |
32 | eZ\Launchpad\Listener\OSXListener:
33 | class:
34 | arguments: [!tagged ezlaunchpad.osx.optimizer]
35 | tags:
36 | - { name: kernel.event_listener, event: console.command, method: onCommandAction }
37 |
38 | # OSX OPTIMIZER
39 | eZ\Launchpad\Core\OSX\Optimizer\D4M:
40 | tags: [ezlaunchpad.osx.optimizer]
41 |
42 | eZ\Launchpad\Core\OSX\Optimizer\NFSVolumes:
43 | tags: [ezlaunchpad.osx.optimizer]
44 |
--------------------------------------------------------------------------------
/docs/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # eZ Launchpad
2 |
3 | ## CHANGELOG
4 |
5 | ### ?.?.?
6 |
7 | - Add support for calling composer ezplatform-install (script) on "initialdata" argument
8 | - Add support for xdebug
9 |
10 |
11 | ### 1.4.0
12 |
13 | - Add SOLR_CORES env variable on solr container to define the core(s) name. (default = "collection1")
14 | - Add DATABASE_PREFIXES env variable on engine container. This var define the prefix used to name the db connection vars (default = "DATABASE"). It's possible to define multiple prefixes to handle multiple db.
15 | - Remove composer.phar manipulation and add composer in the engine image.
16 |
17 | ### 1.3.0
18 |
19 | - First version ready for 2.x with the new directory structure
20 |
21 | ### 1.2.1
22 |
23 | - Apply EZP-28183 change
24 |
25 | ### 1.2.0
26 |
27 | - use Redis for Session for Platform.sh configuration by default
28 | - Wizard Simplification, to remove the questions in 'standard' mode
29 | - Fix TCP port mapping with Memached Admin
30 |
31 | ### 1.1.0
32 |
33 | - ezplatform-http-cache is enabled when not loaded
34 | - Varnish5 and xkey VCL by default
35 | - new Default README.md after initialize
36 | - Simpler Makefile
37 | - Cache are now purged when using Varnish (new ENV var trigger ezplatform to do it)
38 | - Platform.sh optimizations
39 | - Docker-Compose file is more readable
40 | - Fix #7
41 | - Fix #8
42 |
43 |
44 | ### 1.0.0
45 |
46 | - Initial Stable Version
47 |
--------------------------------------------------------------------------------
/docs/LEMP_architecture.puml:
--------------------------------------------------------------------------------
1 | @startuml
2 |
3 | title "Development Architecture - LEMP"
4 |
5 | cloud "Exposed Ports" {
6 | () XX080 as SymfonyDevModePort
7 | () XX081 as SymfonyProdModePort
8 | () XX082 as SymfonyProdModeVarnishPort
9 |
10 | () XX083 as RedisAdminPort
11 | () XX983 as SorlPort
12 | () XX084 as DatabaseAdminPort
13 | () XX306 as DatabaseEnginePort
14 | () XX180 as MailcatcherPort
15 | }
16 |
17 | node "nginx" {
18 | [PROD]
19 | [DEV]
20 | }
21 |
22 | node "Engine" as engine {
23 | [PHP-FPM] as PhpFPM
24 | [PHP-CLI] as PhpCli
25 | }
26 |
27 | node "MySQL or MariaDB" as db {
28 | database "ezplatform" as StandardDB
29 | }
30 |
31 | node "Redis" as appcache {
32 | }
33 |
34 | node "Varnish 4.x" as varnish {
35 | }
36 |
37 | node "Redis Admin" as redisadmin {
38 | }
39 |
40 | node "Mailcatcher" as mailcatcher {
41 | }
42 |
43 | node "Adminer" as dbadmin {
44 | }
45 |
46 | node "Solr" as solr {
47 | }
48 |
49 | RedisAdminPort -> redisadmin: Web Interface
50 | DatabaseEnginePort ---> db: TCP forward
51 | MailcatcherPort -> mailcatcher: Web Interface
52 | DatabaseAdminPort --> dbadmin: Web Interface
53 | SorlPort -> solr
54 |
55 | SymfonyDevModePort --> DEV: Web
56 | SymfonyProdModePort --> PROD: Web
57 | SymfonyProdModeVarnishPort --> varnish: Web
58 | varnish --> PROD
59 |
60 | DEV --> PhpFPM
61 | PROD --> PhpFPM
62 |
63 | engine -up--> db
64 | engine --> appcache
65 | engine --> mailcatcher
66 | engine ---> solr
67 |
68 | redisadmin --> appcache
69 | dbadmin ---> db
70 |
71 | @enduml
72 |
--------------------------------------------------------------------------------
/docs/css/ezlaunchpad.css:
--------------------------------------------------------------------------------
1 |
2 | a, a:hover, h1 i,h2 i,h3 i,h4 i,h5 i,h6 i {
3 | color: #E61851;
4 | }
5 |
6 |
7 | .container .text-muted {
8 | margin: 20px 0;
9 | }
10 |
11 | .highlight {
12 | position: relative;
13 | }
14 |
15 | .highlight .to-clipboard {
16 | position: absolute;
17 | top: 0;
18 | right: 0;
19 | z-index: 10;
20 | display: block;
21 | padding: 5px 8px;
22 | font-size: 12px;
23 | color: #767676;
24 | cursor: pointer;
25 | background-color: #fff;
26 | border: 1px solid #e1e1e8;
27 | border-radius: 0 4px 0 4px;
28 | }
29 |
30 | .ezlp-submenu li, .ezlp-submenu li a {
31 | height: auto;
32 | }
33 |
34 | .clickable {
35 | cursor:pointer;
36 | }
37 |
38 | .footer-content {
39 | color: #f2f2f2;
40 | background-color: #000;
41 | padding-top: 50px;
42 | padding-bottom: 50px;
43 | }
44 |
45 | .footer-content a {
46 | color: #fff;
47 | text-decoration: none;
48 | }
49 |
50 | .copyright-content {
51 | background-color: #666;
52 | color: #BFBFBF;
53 | padding-top: 20px;
54 | padding-bottom: 20px;
55 | }
56 |
57 | .copyright-content a, .copyright-content a:hover {
58 | color: #ff4713;
59 | }
60 |
--------------------------------------------------------------------------------
/docs/ez.phar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ezsystems/launchpad/f5704fc0399dc1977e0b3ed12de734a34e1be00f/docs/ez.phar
--------------------------------------------------------------------------------
/docs/ez.phar.pubkey:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzzMKkvmPQvqdPGax6BQz
3 | Wd4U3M2O2s/bgbX2KF5sXWitSzccrnoje2TIcWfhnRZXiqcgbagxconI2V3WJP7U
4 | oiZ2iqhJs3WqEdciYmX8tdc3JMAMaNMkhpEDcJcXnhYVuoA/i2Ad3RAfnW/XIUYy
5 | anD3VQNZTdu/oolhv5/kbMQdUFaf5NnI+j13qPQjoaqNOZh/5CaOkRYUnDdNPn7C
6 | vzyF9YQ3nW5wSrWR9TqkvIeVoJ/4kdemeEh+DYZZlNa55f/nPkW2SXiXC4UJfbA/
7 | EkfAJWSdJNR73XtCqen96BV8zeE0VsVGouPRFtKasNCPkhsUzpbf77QNnESatuDi
8 | gaoYWZCRQJ3tmgQBV4o35H2ZI36mz48z2vUuqdtb4ONTKtc5yEZZNiqfDARAys5a
9 | nr4V3CGifCoMq/2bmF4QxDc0//J7aDV63dc3W+b7dYOoCs5RvPLSAzei7QCvQmwN
10 | 3ihCp5qJurqm4boZVTiEtwGMKYPe04gHQKivwB196wBLMhgMpAw7tBebG6uJl2i2
11 | 0oe08WAASJ7agiE04gM0+0e4xHXopTfOjYtiLm4khLtHm4vORoCbX1hm+ZYo8fL5
12 | ynl9opd2vopwukVIC2t2WXGa/0SLVcygnjq4ow4it6zq+zPemS/AiR23//UMKr8h
13 | gkX9cNgYQNT9Ko+Plqe+kT8CAwEAAQ==
14 | -----END PUBLIC KEY-----
15 |
--------------------------------------------------------------------------------
/docs/images/puml/LAMP_architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ezsystems/launchpad/f5704fc0399dc1977e0b3ed12de734a34e1be00f/docs/images/puml/LAMP_architecture.png
--------------------------------------------------------------------------------
/docs/images/puml/LEMP_architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ezsystems/launchpad/f5704fc0399dc1977e0b3ed12de734a34e1be00f/docs/images/puml/LEMP_architecture.png
--------------------------------------------------------------------------------
/docs/install.bash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | EZ_HOME="$HOME/.ezlaunchpad"
4 | mkdir -p $EZ_HOME
5 | cd $EZ_HOME
6 |
7 | php -r "copy('https://ezsystems.github.io/launchpad/installer', 'installer');"
8 | php installer
9 | rm installer
10 |
11 | ln -sf $EZ_HOME/ez.phar $HOME/ez
12 | chmod +x $HOME/ez
13 |
14 | echo "You can now use eZ Launchpad by running: ~/ez"
15 | echo ""
16 | echo "- You may want to put ~/ez in you PATH"
17 | echo "- You may want to creat an alias (in your .zshrc or .bashrc) alias ez='~/ez'"
18 |
19 | ~/ez
20 |
--------------------------------------------------------------------------------
/docs/install_curl.bash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # @see: install.bash, this one is a copy/paste to avoid BC break
4 |
5 | EZ_HOME="$HOME/.ezlaunchpad"
6 | mkdir -p $EZ_HOME
7 | cd $EZ_HOME
8 |
9 | php -r "copy('https://ezsystems.github.io/launchpad/installer', 'installer');"
10 | php installer
11 | rm installer
12 |
13 | ln -sf $EZ_HOME/ez.phar $HOME/ez
14 | chmod +x $HOME/ez
15 |
16 | echo "You can now use eZ Launchpad by running: ~/ez"
17 | echo ""
18 | echo "- You may want to put ~/ez in you PATH"
19 | echo "- You may want to creat an alias (in your .zshrc or .bashrc) alias ez='~/ez'"
20 |
21 | ~/ez
22 |
--------------------------------------------------------------------------------
/docs/install_wget.bash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # @see: install.bash, this one is a copy/paste to avoid BC break
4 |
5 | EZ_HOME="$HOME/.ezlaunchpad"
6 | mkdir -p $EZ_HOME
7 | cd $EZ_HOME
8 |
9 | php -r "copy('https://ezsystems.github.io/launchpad/installer', 'installer');"
10 | php installer
11 | rm installer
12 |
13 | ln -sf $EZ_HOME/ez.phar $HOME/ez
14 | chmod +x $HOME/ez
15 |
16 | echo "You can now use eZ Launchpad by running: ~/ez"
17 | echo ""
18 | echo "- You may want to put ~/ez in you PATH"
19 | echo "- You may want to creat an alias (in your .zshrc or .bashrc) alias ez='~/ez'"
20 |
21 | ~/ez
22 |
--------------------------------------------------------------------------------
/docs/installer:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | [
13 | 'method' => 'GET',
14 | 'header' => [
15 | 'User-Agent: eZ Launchpad Installer'
16 | ]
17 | ]
18 | ]
19 | );
20 | $release = json_decode(
21 | file_get_contents(
22 | "https://api.github.com/repos/{$repo}/releases?draft=false&prerelease=false",
23 | false,
24 | $context
25 | ),
26 | false
27 | )[0];
28 |
29 | unset($content);
30 | $assetUrl = $release->assets[0]->browser_download_url;
31 |
32 | file_put_contents(
33 | "ez.phar",
34 | file_get_contents(
35 | $assetUrl,
36 | false,
37 | $context
38 | )
39 | );
40 |
41 | file_put_contents(
42 | "ez.phar.pubkey",
43 | file_get_contents(
44 | "https://ezsystems.github.io/launchpad/ez.phar.pubkey",
45 | false,
46 | $context
47 | )
48 | );
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/docs/js/ezlaunchpad.js:
--------------------------------------------------------------------------------
1 | $(function () {
2 | var clipboard = new Clipboard('button.to-clipboard', {
3 | text: function (trigger) {
4 | return $(trigger).parent().find("code:first").text();
5 | }
6 | });
7 | clipboard.on('success', function (e) {
8 | var $trigger = $(e.trigger);
9 | $trigger.text("Copied!");
10 | setTimeout(function () {
11 | $trigger.html(' Copy');
12 | }, 3000);
13 | e.clearSelection();
14 | });
15 |
16 | });
17 |
--------------------------------------------------------------------------------
/payload/README.md:
--------------------------------------------------------------------------------
1 | eZ with eZ Launchpad
2 | ====================
3 |
4 | This project has been generated by eZ Launchpad.
5 |
6 | You can find the full documentation here: https://ezsystems.github.io/launchpad
7 |
8 | You can find the Launchpad repository here: https://github.com/ezsystems/launchpad
9 |
10 | ## Install and use
11 |
12 | 1. Install the launchpad with **curl** OR **wget**:
13 | ```sh
14 | $ curl -LSs https://ezsystems.github.io/launchpad/install_curl.bash | bash
15 |
16 | # OR
17 |
18 | $ wget -O - "https://ezsystems.github.io/launchpad/install_wget.bash" | bash
19 | ```
20 |
21 | 2. Start the docker containers:
22 | ```sh
23 | $ ~/ez start
24 | ```
25 |
26 | 3. Load data:
27 | ```
28 | $ ~/ez importdata
29 | ```
30 |
31 | 4. Ready to use and develop:
32 | ```
33 | # View containers:
34 | $ ~/ez ps
35 |
36 | # Enter the engine container:
37 | $ ~/ez enter
38 |
39 | # Full command and alias list:
40 | $ ~/ez
41 | ```
42 |
--------------------------------------------------------------------------------
/payload/dev/docker-compose-osx.yml:
--------------------------------------------------------------------------------
1 | version: '2.2'
2 | services:
3 | engine:
4 | volumes:
5 | - "nfsmount:${PROJECTMAPPINGFOLDER}"
6 | volumes:
7 | nfsmount:
8 | driver: local
9 | driver_opts:
10 | type: nfs
11 | o: addr=host.docker.internal,rw,nolock,hard,nointr,nfsvers=3
12 | device: ":${PROJECTCOMPOSEPATH}/"
13 |
--------------------------------------------------------------------------------
/payload/dev/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '2.2'
2 | services:
3 | nginx:
4 | image: nginx:stable-alpine
5 | volumes:
6 | - "${PROJECTCOMPOSEPATH}/${PROVISIONINGFOLDERNAME}/dev/nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro"
7 | - "${PROJECTCOMPOSEPATH}/${PROVISIONINGFOLDERNAME}/dev/nginx/entrypoint.bash:/entrypoint.bash:ro"
8 | - "${PROJECTCOMPOSEPATH}/ezplatform/doc/nginx/ez_params.d:/etc/nginx/ez_params.d:ro"
9 | depends_on:
10 | - engine
11 | volumes_from:
12 | - engine:ro
13 | entrypoint: /entrypoint.bash
14 | ports:
15 | - "${PROJECTPORTPREFIX}080:80"
16 | - "${PROJECTPORTPREFIX}081:81"
17 | environment:
18 | - PROJECTMAPPINGFOLDER
19 |
20 | engine:
21 | build: ./engine/
22 | volumes:
23 | - "${PROJECTCOMPOSEPATH}/${PROVISIONINGFOLDERNAME}/dev/engine/php.ini:/usr/local/etc/php/php.ini:ro"
24 | - "${PROJECTCOMPOSEPATH}:${PROJECTMAPPINGFOLDER}:rw"
25 | - "${HOST_COMPOSER_CACHE_DIR}:${COMPOSER_CACHE_DIR}:rw"
26 | - "${PROJECTCOMPOSEPATH}/${PROVISIONINGFOLDERNAME}/dev/solr:/ezsolr:rw"
27 | shm_size: 754M
28 | environment:
29 | - COMPOSER_CACHE_DIR
30 | - PROJECTMAPPINGFOLDER
31 | - DEV_UID
32 | - DEV_GID
33 | - XDEBUG_ENABLED
34 | - "XDEBUG_CONFIG=remote_host=172.17.0.1"
35 | - "PHP_IDE_CONFIG=serverName=ezplatform"
36 | - "EZP_TEST_REST_HOST=nginx"
37 | - "DATABASE_PREFIXES=DATABASE"
38 | - "DATABASE_PLATFORM=mysql"
39 | - "DATABASE_DRIVER=pdo_mysql"
40 | - "DATABASE_USER=root"
41 | - "DATABASE_NAME=ezplatform"
42 | - "DATABASE_PASSWORD=ezplatform"
43 | - "SYMFONY_SECRET=eZlaunchpad20Secret09Dev83ModeZ"
44 | - "APP_SECRET=eZlaunchpad20Secret09Dev83ModeZ"
45 | - "DATABASE_HOST=db"
46 | - "CUSTOM_CACHE_POOL=singleredis"
47 | - "CACHE_HOST=redis"
48 | - "CACHE_REDIS_PORT=6379"
49 | - "CACHE_POOL=cache.redis"
50 | - "CACHE_DSN=redis:6379"
51 | - "SEARCH_ENGINE=solr"
52 | - "SOLR_DSN=http://solr:8983/solr"
53 | - "SYMFONY_TMP_DIR=/tmp/ezplatformcache/"
54 | - "APP_CACHE_DIR=/tmp/ezplatformcache/"
55 | - "APP_LOG_DIR=/tmp/ezplatformlogs/"
56 | - "HTTPCACHE_VARNISH_INVALIDATE_TOKEN=eZlaunchpad20Secret09Varnish"
57 | - "SESSION_HANDLER_ID=ezplatform.core.session.handler.native_redis"
58 | - "SESSION_SAVE_PATH=tcp://redis:6379"
59 | db:
60 | image: mariadb:10.3
61 | environment:
62 | - "MYSQL_ROOT_PASSWORD=ezplatform"
63 | ports:
64 | - "${PROJECTPORTPREFIX}306:3306"
65 |
66 | varnish:
67 | image: plopix/docker-varnish6
68 | volumes:
69 | - "${PROJECTCOMPOSEPATH}/${PROVISIONINGFOLDERNAME}/dev/varnish/varnish.vcl:/etc/varnish/default.vcl:ro"
70 | ports:
71 | - "${PROJECTPORTPREFIX}082:80"
72 | depends_on:
73 | - nginx
74 |
75 | solr:
76 | image: solr:7.7
77 | volumes:
78 | - "${PROJECTCOMPOSEPATH}/${PROVISIONINGFOLDERNAME}/dev/solr/entrypoint.bash:/entrypoint.bash:ro"
79 | volumes_from:
80 | - engine:rw
81 | ports:
82 | - "${PROJECTPORTPREFIX}983:8983"
83 | entrypoint: /entrypoint.bash
84 | depends_on:
85 | - engine
86 | environment:
87 | - DEV_UID
88 | - DEV_GID
89 | - PROJECTMAPPINGFOLDER
90 | - SOLR_CORES=collection1
91 |
92 | # Mailcatcher
93 | mailcatcher:
94 | image: schickling/mailcatcher
95 | ports:
96 | - "${PROJECTPORTPREFIX}180:1080"
97 |
98 | # Adminer
99 | adminer:
100 | image: adminer:latest
101 | ports:
102 | - "${PROJECTPORTPREFIX}084:8080"
103 |
104 | # REDIS
105 | redis:
106 | image: redis:latest
107 | depends_on:
108 | - engine
109 |
110 | redisadmin:
111 | image: rediscommander/redis-commander:latest
112 | environment:
113 | - REDIS_HOST=redis
114 | ports:
115 | - "${PROJECTPORTPREFIX}083:8081"
116 |
117 | # Blackfire
118 | blackfire:
119 | image: blackfire/blackfire
120 | environment:
121 | - BLACKFIRE_CLIENT_ID
122 | - BLACKFIRE_CLIENT_TOKEN
123 | - BLACKFIRE_SERVER_ID
124 | - BLACKFIRE_SERVER_TOKEN
125 |
126 | # Mysql-Proxy
127 | mysqlproxy:
128 | image: plopix/docker-mysqlproxyprofiler
129 | environment:
130 | - 'BACKEND=db:3306'
131 |
--------------------------------------------------------------------------------
/payload/dev/engine/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM plopix/docker-php-ez-engine:7.4
2 | MAINTAINER Plopix
3 |
4 | ENV XDEBUG_ENABLED=0
5 |
6 | RUN mkdir /usr/local/etc/php/enable-xdebug
7 |
8 | COPY xdebug.ini /usr/local/etc/php/enable-xdebug/99-xdebug.ini
9 |
10 | COPY entrypoint.bash /entrypoint.bash
11 | RUN chmod +x /entrypoint.bash
12 | ENTRYPOINT ["/entrypoint.bash"]
13 | CMD ["php-fpm"]
14 |
--------------------------------------------------------------------------------
/payload/dev/engine/entrypoint.bash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ORIGPASSWD=$(cat /etc/passwd | grep www-data)
4 | ORIG_UID=$(echo "$ORIGPASSWD" | cut -f3 -d:)
5 | ORIG_GID=$(echo "$ORIGPASSWD" | cut -f4 -d:)
6 | ORIG_HOME=$(echo "$ORIGPASSWD" | cut -f6 -d:)
7 | DEV_UID=${DEV_UID:=$ORIG_UID}
8 | DEV_GID=${DEV_GID:=$ORIG_GID}
9 |
10 | if [ "$DEV_UID" -ne "$ORIG_UID" ] || [ "$DEV_GID" -ne "$ORIG_GID" ]; then
11 | groupmod -g "$DEV_GID" www-data
12 | usermod -u "$DEV_UID" -g "$DEV_GID" www-data
13 | fi
14 |
15 | # Create .composer in advance and set the permissions
16 | mkdir -p /var/www/.composer && chown www-data:www-data /var/www/.composer
17 | chown www-data:www-data $PROJECTMAPPINGFOLDER
18 |
19 | # give the good permissions to www-data in the container and remove the cache on start
20 | # 2.x
21 | if [ -d $PROJECTMAPPINGFOLDER/ezplatform/var/cache ]; then
22 | rm -rf $PROJECTMAPPINGFOLDER/ezplatform/var/cache
23 | rm -rf $SYMFONY_TMP_DIR/var/cache
24 | chown -R www-data:www-data $PROJECTMAPPINGFOLDER/ezplatform/var/logs
25 | chown -R www-data:www-data $PROJECTMAPPINGFOLDER/ezplatform/web
26 | fi
27 |
28 | if [ ! -f /usr/local/bin/composer ];
29 | then
30 | echo "WARNING: you don't have the last image of the PHP ENGINE"
31 | echo "TO FIX RUN: ~/ez docker:update"
32 | fi
33 | /usr/local/bin/composer self-update --1
34 |
35 | if [ "1" = "${XDEBUG_ENABLED}" ]; then
36 | export PHP_INI_SCAN_DIR=:/usr/local/etc/php/enable-xdebug
37 | fi
38 |
39 | exec "$@"
40 |
--------------------------------------------------------------------------------
/payload/dev/engine/php.ini:
--------------------------------------------------------------------------------
1 | disable_functions =
2 | disable_classes =
3 |
4 | max_execution_time = 120
5 | max_input_time = 90
6 |
7 | display_errors = "On"
8 | log_errors = "On"
9 |
10 | memory_limit = 2048M
11 | post_max_size = 40M
12 | upload_max_filesize = 40M
13 |
14 | session.save_handler = redis
15 | session.save_path = "tcp://redis:6379"
16 |
17 | sendmail_path = /usr/bin/env catchmail --smtp-ip mailcatcher --smtp-port 1025 -f docker@localhost
18 |
19 | extension=blackfire.so
20 | blackfire.agent_socket=tcp://blackfire:8707
21 |
22 | [Date]
23 | date.timezone = "America/Los_Angeles"
24 |
25 |
26 |
--------------------------------------------------------------------------------
/payload/dev/engine/xdebug.ini:
--------------------------------------------------------------------------------
1 | zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20190902/xdebug.so
2 | xdebug.default_enable=1
3 | xdebug.remote_enable=1
4 | xdebug.max_nesting_level=1000
5 | xdebug.idekey=XDEBUG_IDE_KEY
6 | xdebug.remote_connect_back=1
7 |
--------------------------------------------------------------------------------
/payload/dev/nginx/entrypoint.bash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ash
2 |
3 | nginx -g "daemon off;"
4 |
--------------------------------------------------------------------------------
/payload/dev/nginx/nginx.conf:
--------------------------------------------------------------------------------
1 | # GZIP
2 | gzip on;
3 | gzip_disable "msie6";
4 | gzip_proxied any;
5 | gzip_comp_level 6;
6 | gzip_buffers 16 8k;
7 | gzip_http_version 1.1;
8 | gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
9 |
10 | # DEV MODE
11 | server {
12 | listen 80;
13 | server_name _;
14 | # Project Root = project-path-container = /var/www/html/project
15 | # Would be great to get that from ENV var PROJECTMAPPINGFOLDER
16 | root "/var/www/html/project/ezplatform/public";
17 |
18 | # FOR DFS
19 | # include ez_params.d/ez_rewrite_dfsimage_params;
20 |
21 | # ez rewrite rules
22 | include ez_params.d/ez_rewrite_params;
23 |
24 | # upload max size
25 | client_max_body_size 40M;
26 |
27 | # FPM fastcgi_read_timeout
28 | fastcgi_read_timeout 30;
29 |
30 | location / {
31 | location ~ ^/index\.php(/|$) {
32 | include ez_params.d/ez_fastcgi_params;
33 | fastcgi_pass engine:9000;
34 | fastcgi_param APP_ENV dev;
35 | fastcgi_param RUNNING_ENV DOCKER;
36 | }
37 | }
38 | include ez_params.d/ez_server_params;
39 | }
40 |
41 | # PROD MODE - Symfony Reverse Proxy
42 | server {
43 | listen 81;
44 | server_name _;
45 | # Project Root = project-path-container = /var/www/html/project
46 | # Would be great to get that from ENV var PROJECTMAPPINGFOLDER
47 | root "/var/www/html/project/ezplatform/public";
48 |
49 | include ez_params.d/ez_prod_rewrite_params;
50 |
51 | # FOR DFS
52 | # include ez_params.d/ez_rewrite_dfsimage_params;
53 |
54 | # ez rewrite rules
55 | include ez_params.d/ez_rewrite_params;
56 |
57 | # upload max size
58 | client_max_body_size 40M;
59 |
60 | # FPM fastcgi_read_timeout
61 | fastcgi_read_timeout 30;
62 |
63 | location / {
64 | location ~ ^/index\.php(/|$) {
65 | include ez_params.d/ez_fastcgi_params;
66 |
67 | fastcgi_pass engine:9000;
68 | fastcgi_param APP_ENV prod;
69 | fastcgi_param RUNNING_ENV DOCKER;
70 | }
71 | }
72 | include ez_params.d/ez_server_params;
73 | }
74 |
75 |
76 | # PROD MODE - Varnish
77 | server {
78 | listen 82;
79 | server_name _;
80 | # Project Root = project-path-container = /var/www/html/project
81 | # Would be great to get that from ENV var PROJECTMAPPINGFOLDER
82 | root "/var/www/html/project/ezplatform/public";
83 |
84 | include ez_params.d/ez_prod_rewrite_params;
85 |
86 | # FOR DFS
87 | # include ez_params.d/ez_rewrite_dfsimage_params;
88 |
89 | # ez rewrite rules
90 | include ez_params.d/ez_rewrite_params;
91 |
92 | # upload max size
93 | client_max_body_size 40M;
94 |
95 | # FPM fastcgi_read_timeout
96 | fastcgi_read_timeout 30;
97 |
98 | location / {
99 | location ~ ^/index\.php(/|$) {
100 | include ez_params.d/ez_fastcgi_params;
101 |
102 | fastcgi_pass engine:9000;
103 | fastcgi_param APP_ENV prod;
104 | fastcgi_param RUNNING_ENV DOCKER;
105 | fastcgi_param APP_HTTP_CACHE 0;
106 | fastcgi_param HTTPCACHE_PURGE_TYPE varnish;
107 | fastcgi_param HTTPCACHE_PURGE_SERVER 'http://varnish:80';
108 | fastcgi_param TRUSTED_PROXIES "127.0.0.1,localhost,172.0.0.0/8,varnish,192.168.0.0/16";
109 | }
110 | }
111 | include ez_params.d/ez_server_params;
112 | }
113 |
--------------------------------------------------------------------------------
/payload/dev/nginx/nginx_v2.conf:
--------------------------------------------------------------------------------
1 | # GZIP
2 | gzip on;
3 | gzip_disable "msie6";
4 | gzip_proxied any;
5 | gzip_comp_level 6;
6 | gzip_buffers 16 8k;
7 | gzip_http_version 1.1;
8 | gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
9 |
10 | # DEV MODE
11 | server {
12 | listen 80;
13 | server_name _;
14 | # Project Root = project-path-container = /var/www/html/project
15 | # Would be great to get that from ENV var PROJECTMAPPINGFOLDER
16 | root "/var/www/html/project/ezplatform/web";
17 |
18 | # FOR DFS
19 | # include ez_params.d/ez_rewrite_dfsimage_params;
20 |
21 | # ez rewrite rules
22 | include ez_params.d/ez_rewrite_params;
23 |
24 | # upload max size
25 | client_max_body_size 40M;
26 |
27 | # FPM fastcgi_read_timeout
28 | fastcgi_read_timeout 30;
29 |
30 | location / {
31 | location ~ ^/app\.php(/|$) {
32 | include ez_params.d/ez_fastcgi_params;
33 | fastcgi_pass engine:9000;
34 | fastcgi_param SYMFONY_ENV dev;
35 | fastcgi_param RUNNING_ENV DOCKER;
36 | }
37 | }
38 | include ez_params.d/ez_server_params;
39 | }
40 |
41 | # PROD MODE - Symfony Reverse Proxy
42 | server {
43 | listen 81;
44 | server_name _;
45 | # Project Root = project-path-container = /var/www/html/project
46 | # Would be great to get that from ENV var PROJECTMAPPINGFOLDER
47 | root "/var/www/html/project/ezplatform/web";
48 |
49 | include ez_params.d/ez_prod_rewrite_params;
50 |
51 | # FOR DFS
52 | # include ez_params.d/ez_rewrite_dfsimage_params;
53 |
54 | # ez rewrite rules
55 | include ez_params.d/ez_rewrite_params;
56 |
57 | # upload max size
58 | client_max_body_size 40M;
59 |
60 | # FPM fastcgi_read_timeout
61 | fastcgi_read_timeout 30;
62 |
63 | location / {
64 | location ~ ^/app\.php(/|$) {
65 | include ez_params.d/ez_fastcgi_params;
66 |
67 | fastcgi_pass engine:9000;
68 | fastcgi_param SYMFONY_ENV prod;
69 | fastcgi_param RUNNING_ENV DOCKER;
70 | }
71 | }
72 | include ez_params.d/ez_server_params;
73 | }
74 |
75 |
76 | # PROD MODE - Varnish
77 | server {
78 | listen 82;
79 | server_name _;
80 | # Project Root = project-path-container = /var/www/html/project
81 | # Would be great to get that from ENV var PROJECTMAPPINGFOLDER
82 | root "/var/www/html/project/ezplatform/web";
83 |
84 | include ez_params.d/ez_prod_rewrite_params;
85 |
86 | # FOR DFS
87 | # include ez_params.d/ez_rewrite_dfsimage_params;
88 |
89 | # ez rewrite rules
90 | include ez_params.d/ez_rewrite_params;
91 |
92 | # upload max size
93 | client_max_body_size 40M;
94 |
95 | # FPM fastcgi_read_timeout
96 | fastcgi_read_timeout 30;
97 |
98 | location / {
99 | location ~ ^/app\.php(/|$) {
100 | include ez_params.d/ez_fastcgi_params;
101 |
102 | fastcgi_pass engine:9000;
103 | fastcgi_param SYMFONY_ENV prod;
104 | fastcgi_param RUNNING_ENV DOCKER;
105 | fastcgi_param SYMFONY_HTTP_CACHE 0;
106 | fastcgi_param HTTPCACHE_PURGE_TYPE http;
107 | fastcgi_param HTTPCACHE_PURGE_SERVER 'http://varnish:80';
108 | fastcgi_param SYMFONY_TRUSTED_PROXIES "127.0.0.1,localhost,172.0.0.0/8,varnish";
109 | }
110 | }
111 | include ez_params.d/ez_server_params;
112 | }
113 |
--------------------------------------------------------------------------------
/payload/dev/solr/entrypoint.bash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Check if missing template folder
4 | DESTINATION_EZ="/ezsolr/server/ez"
5 | DESTINATION_TEMPLATE="${DESTINATION_EZ}/template"
6 | if [ ! -d ${DESTINATION_TEMPLATE} ]; then
7 | cd $PROJECTMAPPINGFOLDER/ezplatform
8 | mkdir -p ${DESTINATION_TEMPLATE}
9 | cp -R vendor/ezsystems/ezplatform-solr-search-engine/lib/Resources/config/solr/* ${DESTINATION_TEMPLATE}
10 | fi
11 |
12 | # Check for solr config folder (changes btw 6 and 7)
13 | SOURCE_SOLR="/opt/solr/server/solr/configsets/_default/"
14 | if [ ! -d ${SOURCE_SOLR} ]; then
15 | SOURCE_SOLR="/opt/solr/server/solr/configsets/basic_configs/"
16 | fi
17 |
18 | mkdir -p ${DESTINATION_EZ}
19 | if [ ! -f ${DESTINATION_EZ}/solr.xml ]; then
20 | cp /opt/solr/server/solr/solr.xml ${DESTINATION_EZ}
21 | cp ${SOURCE_SOLR}/conf/{currency.xml,solrconfig.xml,stopwords.txt,synonyms.txt,elevate.xml} ${DESTINATION_TEMPLATE}
22 | sed -i.bak '//d' ${DESTINATION_TEMPLATE}/solrconfig.xml
23 | sed -i -e 's/${solr.autoSoftCommit.maxTime:-1}<\/maxTime>/${solr.autoSoftCommit.maxTime:20}<\/maxTime>/g' ${DESTINATION_TEMPLATE}/solrconfig.xml
24 | sed -i -e 's/${solr.data.dir:}<\/dataDir>/\/opt\/solr\/data\/${solr.core.name}<\/dataDir>/g' ${DESTINATION_TEMPLATE}/solrconfig.xml
25 | fi
26 |
27 | SOLR_CORES=${SOLR_CORES:-collection1}
28 | CREATE_CORES=false
29 |
30 | for core in $SOLR_CORES
31 | do
32 | if [ ! -d ${DESTINATION_EZ}/${core} ]; then
33 | CREATE_CORES=true
34 | echo "Found missing core: ${core}"
35 | fi
36 | done
37 |
38 | if [ "$CREATE_CORES" = true ]; then
39 | touch ${DESTINATION_EZ}/solr.creating.cores
40 | echo "Start solr on background to create missing cores"
41 | /opt/solr/bin/solr -s ${DESTINATION_EZ}
42 |
43 | for core in $SOLR_CORES
44 | do
45 | if [ ! -d ${DESTINATION_EZ}/${core} ]; then
46 | /opt/solr/bin/solr create_core -c ${core} -d ${DESTINATION_TEMPLATE}
47 | echo "Core ${core} created."
48 | fi
49 | done
50 | echo "Stop background solr"
51 | /opt/solr/bin/solr stop
52 | rm ${DESTINATION_EZ}/solr.creating.cores
53 | fi
54 |
55 | /opt/solr/bin/solr -s ${DESTINATION_EZ} -f
56 |
--------------------------------------------------------------------------------
/payload/recipes/composer_install.bash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | cd $PROJECTMAPPINGFOLDER
4 |
5 | # As we are doing build and up we might run here before the end of the entrypoint
6 | while true ; do
7 | if [ -d /var/www/.composer ]; then
8 | if ls -la /var/www/.composer | grep -q "www-data"; then
9 | break
10 | fi
11 | fi
12 | echo -n "."
13 | sleep 2
14 | done
15 | echo ""
16 |
17 | if [ ! -f /usr/local/bin/composer ];
18 | then
19 | echo "WARNING: you don't have the last image of the PHP ENGINE"
20 | echo "TO FIX RUN: ~/ez docker:update"
21 | fi
22 |
23 | /usr/local/bin/composer self-update > /dev/null 2>&1
24 |
25 | sleep 2
26 |
--------------------------------------------------------------------------------
/payload/recipes/create_dump.bash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | cd $PROJECTMAPPINGFOLDER
4 |
5 |
6 | mkdir -p data
7 |
8 | DUMP_DIR="$(pwd)/data"
9 | if [ "$1" != "" ] && [ -d "$1" ]; then
10 | if [[ "$1" =~ ^/ ]]; then
11 | DUMP_DIR="$1"
12 | fi
13 | fi
14 |
15 | DATABASE_PREFIXES=${DATABASE_PREFIXES:-DATABASE}
16 |
17 | for prefix in $DATABASE_PREFIXES
18 | do
19 | DATABASE_NAME_VAR=${prefix}_NAME
20 | DATABASE_HOST_VAR=${prefix}_HOST
21 | DATABASE_USER_VAR=${prefix}_USER
22 | DATABASE_PASSWORD_VAR=${prefix}_PASSWORD
23 |
24 | # Wait for the DB
25 | while ! mysqladmin ping -h"${!DATABASE_HOST_VAR}" -u"${!DATABASE_USER_VAR}" -p"${!DATABASE_PASSWORD_VAR}" --silent; do
26 | echo -n "."
27 | sleep 1
28 | done
29 | echo ""
30 |
31 | DB_FILE_NAME="${!DATABASE_NAME_VAR}"
32 |
33 | MYSQLDUMP="mysqldump -h${!DATABASE_HOST_VAR} -u${!DATABASE_USER_VAR} -p${!DATABASE_PASSWORD_VAR}"
34 |
35 | echo "Dumping ${!DATABASE_NAME_VAR} database."
36 | $MYSQLDUMP ${!DATABASE_NAME_VAR} > $DUMP_DIR/$DB_FILE_NAME.sql
37 | gzip -f $DUMP_DIR/$DB_FILE_NAME.sql
38 | echo "${!DATABASE_NAME_VAR} database dumped."
39 | done
40 |
41 |
42 | STORAGE_FILE_NAME="storage"
43 |
44 | if [ "$2" != "" ]; then
45 | STORAGE_FILE_NAME="$2_storage"
46 | fi
47 |
48 | if [ -d $PROJECTMAPPINGFOLDER/ezplatform/web/var ]; then
49 | cd $PROJECTMAPPINGFOLDER/ezplatform/web
50 | tar czvf $DUMP_DIR/$STORAGE_FILE_NAME.tar.gz var/
51 | cd -
52 | echo "Storage dumped from web/."
53 | fi
54 |
55 | if [ -d $PROJECTMAPPINGFOLDER/ezplatform/public/var ]; then
56 | cd $PROJECTMAPPINGFOLDER/ezplatform/public
57 | tar czvf $DUMP_DIR/$STORAGE_FILE_NAME.tar.gz var/
58 | cd -
59 | echo "Storage dumped from public/."
60 | fi
61 |
--------------------------------------------------------------------------------
/payload/recipes/ez_create.bash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | cd $PROJECTMAPPINGFOLDER
4 |
5 | PHP="php"
6 | COMPOSER="$PHP -d memory_limit=-1 /usr/local/bin/composer"
7 | REPO=$1
8 | VERSION=$2
9 |
10 | DATABASE_PREFIXES=${DATABASE_PREFIXES:-DATABASE}
11 | for prefix in $DATABASE_PREFIXES
12 | do
13 | DATABASE_NAME_VAR=${prefix}_NAME
14 | DATABASE_HOST_VAR=${prefix}_HOST
15 | DATABASE_USER_VAR=${prefix}_USER
16 | DATABASE_PASSWORD_VAR=${prefix}_PASSWORD
17 |
18 | # Wait for the DB
19 | while ! mysqladmin ping -h"${!DATABASE_HOST_VAR}" -u"${!DATABASE_USER_VAR}" -p"${!DATABASE_PASSWORD_VAR}" --silent; do
20 | echo -n "."
21 | sleep 1
22 | done
23 | echo ""
24 |
25 | mysql -h"${!DATABASE_HOST_VAR}" -u"${!DATABASE_USER_VAR}" -p"${!DATABASE_PASSWORD_VAR}" -e "CREATE DATABASE ${!DATABASE_NAME_VAR}"
26 | done
27 |
28 | if [ ! -d ezplatform ]; then
29 | echo "Not managed yet."
30 | exit
31 | fi
32 |
33 | CONSOLE="bin/console"
34 | if [ -f ezplatform/app/console ]; then
35 | CONSOLE="app/console"
36 | fi
37 |
38 | # Install
39 | cd ezplatform
40 |
41 | $COMPOSER install --no-interaction
42 |
43 | echo "Installation OK"
44 |
45 |
--------------------------------------------------------------------------------
/payload/recipes/ez_install.bash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | cd $PROJECTMAPPINGFOLDER
4 |
5 | PHP="php"
6 | COMPOSER="$PHP -d memory_limit=-1 /usr/local/bin/composer"
7 | REPO=$1
8 | VERSION=$2
9 | INIT_DATA=$3
10 |
11 | DATABASE_PREFIXES=${DATABASE_PREFIXES:-DATABASE}
12 | for prefix in $DATABASE_PREFIXES
13 | do
14 | DATABASE_NAME_VAR=${prefix}_NAME
15 | DATABASE_HOST_VAR=${prefix}_HOST
16 | DATABASE_USER_VAR=${prefix}_USER
17 | DATABASE_PASSWORD_VAR=${prefix}_PASSWORD
18 |
19 | # Wait for the DB
20 | while ! mysqladmin ping -h"${!DATABASE_HOST_VAR}" -u"${!DATABASE_USER_VAR}" -p"${!DATABASE_PASSWORD_VAR}" --silent; do
21 | echo -n "."
22 | sleep 1
23 | done
24 | echo ""
25 |
26 | mysql -h"${!DATABASE_HOST_VAR}" -u"${!DATABASE_USER_VAR}" -p"${!DATABASE_PASSWORD_VAR}" -e "CREATE DATABASE ${!DATABASE_NAME_VAR}"
27 | done
28 |
29 | echo "Installation eZ Platform ($REPO:$VERSION:$INIT_DATA) in the container"
30 |
31 | # Install
32 | $COMPOSER create-project --no-interaction $REPO ezplatform $VERSION
33 | cd ezplatform
34 |
35 | MAJOR_VERSION=`echo $VERSION | cut -c 1-2`
36 |
37 | # Do some cleaning
38 | ## Folder
39 | rm -rf bin/.ci bin/.travis
40 |
41 | CONSOLE="bin/console"
42 | if [ -f app/console ]; then
43 | CONSOLE="app/console"
44 | fi
45 |
46 |
47 | # Prefer install via composer alias (added in v2.2, required for eZ Commerce)
48 | if $COMPOSER run-script -l | grep -q " $INIT_DATA "; then
49 | $COMPOSER run-script $INIT_DATA
50 | else
51 | $PHP $CONSOLE ezplatform:install $INIT_DATA
52 | fi
53 |
54 |
55 |
56 | echo "Installation OK"
57 |
58 |
--------------------------------------------------------------------------------
/payload/recipes/ez_install_solr.bash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | PROVISIONING=$1
4 | ACTION=$2
5 |
6 | DESTINATION_EZ="/ezsolr/server/ez"
7 | DESTINATION_TEMPLATE="$DESTINATION_EZ/template"
8 | PHP="php"
9 |
10 | if [ $ACTION == "COMPOSER_INSTALL" ]; then
11 | # it is run on the engine
12 | cd $PROJECTMAPPINGFOLDER/ezplatform
13 | mkdir -p $DESTINATION_TEMPLATE
14 | cp -R vendor/ezsystems/ezplatform-solr-search-engine/lib/Resources/config/solr/* $DESTINATION_TEMPLATE
15 | # simplest way to allow solr to add the conf here... from its own container
16 | # We could do better by extending the Dockerfile and build.. but it is also less "generic"
17 | chmod -R 777 $DESTINATION_EZ
18 | fi
19 |
20 | if [ $ACTION == "INDEX" ]; then
21 | # it is run on the engine
22 | until wget -q -O - http://solr:8983 | grep -q -i solr; do
23 | echo -n "."
24 | sleep 2
25 | done
26 | # wait cores
27 | sleep 15
28 | echo "Solr is running"
29 | cd $PROJECTMAPPINGFOLDER/ezplatform
30 | CONSOLE="bin/console"
31 | if [ -f app/console ]; then
32 | CONSOLE="app/console"
33 | fi
34 | $PHP $CONSOLE --env=prod ezplatform:reindex
35 | fi
36 |
37 | if [ $ACTION == "CREATE_CORE" ]; then
38 | # it is run on the solr
39 | until wget -q -O - http://localhost:8983 | grep -q -i solr; do
40 | echo -n "."
41 | sleep 2
42 | done
43 | # wait until create cores from solr entry point is done
44 | until [ ! -f ${DESTINATION_EZ}/solr.creating.cores ]; do
45 | echo -n "c"
46 | sleep 2
47 | done
48 |
49 | echo "Solr is running"
50 |
51 | SOLR_CORES=${SOLR_CORES:-collection1}
52 | for core in $SOLR_CORES
53 | do
54 | if [ ! -d ${DESTINATION_EZ}/${core} ]; then
55 | /opt/solr/bin/solr create_core -c ${core} -d $DESTINATION_TEMPLATE
56 | echo "Core ${core} created."
57 | fi
58 | done
59 |
60 | fi
61 |
62 |
--------------------------------------------------------------------------------
/payload/recipes/ibexa_install.bash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | cd $PROJECTMAPPINGFOLDER
4 |
5 | PHP="php"
6 | COMPOSER="$PHP -d memory_limit=-1 /usr/local/bin/composer"
7 | REPO=$1
8 | VERSION=$2
9 | INIT_DATA=$3
10 | DATABASE_PREFIXES=${DATABASE_PREFIXES:-DATABASE}
11 | CONSOLE="bin/console"
12 |
13 | for prefix in $DATABASE_PREFIXES
14 | do
15 | DATABASE_NAME_VAR=${prefix}_NAME
16 | DATABASE_HOST_VAR=${prefix}_HOST
17 | DATABASE_USER_VAR=${prefix}_USER
18 | DATABASE_PASSWORD_VAR=${prefix}_PASSWORD
19 |
20 | # Wait for the DB
21 | while ! mysqladmin ping -h"${!DATABASE_HOST_VAR}" -u"${!DATABASE_USER_VAR}" -p"${!DATABASE_PASSWORD_VAR}" --silent; do
22 | echo -n "."
23 | sleep 1
24 | done
25 | echo ""
26 |
27 | mysql -h"${!DATABASE_HOST_VAR}" -u"${!DATABASE_USER_VAR}" -p"${!DATABASE_PASSWORD_VAR}" -e "CREATE DATABASE ${!DATABASE_NAME_VAR}"
28 | done
29 |
30 | echo "Installation Ibexa ($REPO - $VERSION) in the container"
31 |
32 | # Install ibexa/website-skeleton
33 | echo "Install ibexa/website-skeleton"
34 | $COMPOSER create-project --no-interaction $REPO-skeleton ezplatform $VERSION
35 | cd ezplatform
36 | # Copy nginx conf
37 | echo "Getting the NGINX config"
38 | wget https://github.com/ibexa/docker/archive/main.zip
39 | unzip main.zip
40 | mkdir -p doc
41 | cp -r docker-main/templates/nginx doc/
42 | rm -rf docker-main
43 | rm main.zip
44 |
45 | # Add .env.local to set database configuration
46 | echo "Add .env.local to set database configuration"
47 | echo "DATABASE_URL=\${DATABASE_PLATFORM}://\${DATABASE_USER}:\${DATABASE_PASSWORD}@\${DATABASE_HOST}:\${DATABASE_PORT}/\${DATABASE_NAME}?serverVersion=\${DATABASE_VERSION}" > ".env.local"
48 |
49 | # Test the package version
50 | if [ "$REPO" != "ibexa/oss" ]; then
51 | echo "configure auth updates.ibexa.co"
52 | $COMPOSER config repositories.ibexa composer https://updates.ibexa.co
53 | fi
54 |
55 | MAJOR_VERSION=`echo $VERSION | cut -c 1-2`
56 |
57 | # Do some cleaning
58 | ## Folder
59 | rm -rf bin/.ci bin/.travis
60 |
61 | echo "Installation Ibexa $REPO OK"
62 |
63 | # Prefer install via composer alias (added in v2.2, required for eZ Commerce)
64 | if $COMPOSER run-script -l | grep -q " $INIT_DATA "; then
65 | $COMPOSER run-script $INIT_DATA
66 | else
67 | echo "php bin/console ibexa:install "
68 | $PHP $CONSOLE ibexa:install $INIT_DATA
69 | fi
70 | echo "php bin/console ibexa:graphql:generate-schema"
71 | $PHP $CONSOLE ibexa:graphql:generate-schema
72 | echo "composer run post-update-cmd"
73 | $COMPOSER run-script post-install-cmd
74 |
75 | echo "Database init OK"
76 |
--------------------------------------------------------------------------------
/payload/recipes/import_dump.bash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | cd $PROJECTMAPPINGFOLDER
4 |
5 | DUMP_DIR="$(pwd)/data"
6 | if [ "$1" != "" ] && [ -d "$1" ]; then
7 | if [[ "$1" =~ ^/ ]]; then
8 | DUMP_DIR="$1"
9 | fi
10 | fi
11 |
12 | DATABASE_PREFIXES=${DATABASE_PREFIXES:-DATABASE}
13 |
14 | for prefix in $DATABASE_PREFIXES
15 | do
16 | DATABASE_NAME_VAR=${prefix}_NAME
17 | DATABASE_HOST_VAR=${prefix}_HOST
18 | DATABASE_USER_VAR=${prefix}_USER
19 | DATABASE_PASSWORD_VAR=${prefix}_PASSWORD
20 |
21 | # Wait for the DB
22 | while ! mysqladmin ping -h"${!DATABASE_HOST_VAR}" -u"${!DATABASE_USER_VAR}" -p"${!DATABASE_PASSWORD_VAR}" --silent; do
23 | echo -n "."
24 | sleep 1
25 | done
26 | echo ""
27 |
28 | DB_FILE_NAME="${!DATABASE_NAME_VAR}"
29 | DB_FILE_PATH="$DUMP_DIR/$DB_FILE_NAME.sql"
30 |
31 | MYSQL="mysql -h${!DATABASE_HOST_VAR} -u${!DATABASE_USER_VAR} -p${!DATABASE_PASSWORD_VAR}"
32 |
33 | echo "Importing ${!DATABASE_NAME_VAR} database."
34 | zcat $DB_FILE_PATH | $MYSQL ${!DATABASE_NAME_VAR}
35 | echo "${!DATABASE_NAME_VAR} database imported."
36 | done
37 |
38 |
39 | STORAGE_FILE_NAME="storage"
40 | if [ "$2" != "" ]; then
41 | STORAGE_FILE_NAME="$2_storage"
42 | fi
43 |
44 | STORAGE_FILE_PATH="$DUMP_DIR/$STORAGE_FILE_NAME.tar.gz"
45 |
46 | if [ ! -d ezplatform ]; then
47 | echo "Not managed yet."
48 | exit
49 | fi
50 |
51 | if [ -f $STORAGE_FILE_PATH ]; then
52 | if [ -d ezplatform/web ]; then
53 | if [ -d "ezplatform/web/var" ]; then
54 | rm -rf ezplatform/web/var
55 | fi
56 | tar xvzf $STORAGE_FILE_PATH -C ezplatform/web/
57 | echo "Storage imported to web/."
58 | fi
59 | if [ -d ezplatform/public ]; then
60 | if [ -d "ezplatform/public/var" ]; then
61 | rm -rf ezplatform/public/var
62 | fi
63 | tar xvzf $STORAGE_FILE_PATH -C ezplatform/public/
64 | echo "Storage imported to public/."
65 | fi
66 | fi
67 |
--------------------------------------------------------------------------------
/scripts/buildbox.bash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | BASEDIR=$(dirname $0)
3 | PHP="env php "
4 | source ${BASEDIR}/functions
5 | PROJECTDIR="${BASEDIR}/../"
6 |
7 | cd ${PROJECTDIR}
8 |
9 | echoTitle "******** Build it! ********"
10 | ulimit -Sn 4096
11 |
12 | if [ ! -f composer.phar ]; then
13 | echoInfo "Install composer.phar before..."
14 | curl -s http://getcomposer.org/installer | $PHP
15 | echoAction "Building now..."
16 | fi
17 | if [ ! -f box.phar ]; then
18 | echoInfo "Install box.phar before..."
19 | curl -LSs https://box-project.github.io/box2/installer.php | $PHP
20 | echoAction "Building now..."
21 | fi
22 |
23 | $PHP composer.phar install --no-dev > /dev/null 2>&1
24 | $PHP -d "phar.readonly=false" box.phar build -vvv
25 | $PHP composer.phar install > /dev/null 2>&1
26 |
27 | echoSuccess "Done."
28 | exit 0;
29 |
--------------------------------------------------------------------------------
/scripts/codechecker.bash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | BASEDIR=$(dirname $0)
4 | PHP="env php"
5 |
6 | source ${BASEDIR}/functions
7 | PROJECTDIR="${BASEDIR}/../"
8 |
9 | if [ -z "$1" ]; then
10 | SRC="src/"
11 | else
12 | SRC="$1"
13 | fi
14 |
15 | cd ${PROJECTDIR}
16 |
17 | echoTitle "******** Mess Detector ********"
18 | $PHP ./vendor/bin/phpmd $SRC text .cs/md_ruleset.xml
19 | $PHP ./vendor/bin/phpmd tests/Tests text .cs/md_ruleset.xml
20 |
21 | echoTitle "******** CodeFixer ************"
22 | $PHP ./vendor/bin/php-cs-fixer fix --config=.cs/.php_cs.php
23 |
24 | echoTitle "******** CodeSniffer **********"
25 | $PHP ./vendor/bin/phpcs --standard=.cs/cs_ruleset.xml --extensions=php $SRC
26 | $PHP ./vendor/bin/phpcs --standard=.cs/cs_ruleset.xml --extensions=php tests/Tests
27 |
28 | echoSuccess "Done."
29 | exit 0;
30 |
--------------------------------------------------------------------------------
/scripts/functions:
--------------------------------------------------------------------------------
1 | #-- Vars
2 | RESTORE=$(echo -en '\033[0m')
3 | RED=$(echo -en '\033[00;31m')
4 | GREEN=$(echo -en '\033[00;32m')
5 | YELLOW=$(echo -en '\033[00;33m')
6 | BLUE=$(echo -en '\033[00;34m')
7 | MAGENTA=$(echo -en '\033[00;35m')
8 | PURPLE=$(echo -en '\033[00;35m')
9 | CYAN=$(echo -en '\033[00;36m')
10 | LIGHTGRAY=$(echo -en '\033[00;37m')
11 | LRED=$(echo -en '\033[01;31m')
12 | LGREEN=$(echo -en '\033[01;32m')
13 | LYELLOW=$(echo -en '\033[01;33m')
14 | LBLUE=$(echo -en '\033[01;34m')
15 | LMAGENTA=$(echo -en '\033[01;35m')
16 | LPURPLE=$(echo -en '\033[01;35m')
17 | LCYAN=$(echo -en '\033[01;36m')
18 | WHITE=$(echo -en '\033[01;37m')
19 | BOLD=$(echo -en '\033[1m')
20 |
21 |
22 | #-- Functions
23 |
24 | f_startColor ()
25 | {
26 | echo -en "$1"
27 | }
28 |
29 | f_resetColor ()
30 | {
31 | echo -en "${RESTORE}"
32 | }
33 |
34 | echoInfo ()
35 | {
36 | echo "${CYAN}[${RESTORE}${BOLD}*${CYAN}]${RESTORE} $1"
37 | }
38 |
39 | echoAction ()
40 | {
41 | echo "${RED}[${LBLUE}ACTION${RESTORE}${RED}]${RESTORE} $1 ${RESTORE}"
42 | }
43 |
44 | echoSuccess ()
45 | {
46 | echo "${LRED}[${BOLD}${LGREEN}OK${RESTORE}${LRED}]${RESTORE} $1 ${RESTORE}"
47 | }
48 |
49 | echoNothing ()
50 | {
51 | echo "${LRED}[${BOLD}${LGREEN}-${RESTORE}${LRED}]${RESTORE} $1 ${RESTORE}"
52 | }
53 |
54 | echoTitle ()
55 | {
56 | echo "${BOLD}${LPURPLE}====${RESTORE} ${LYELLOW}$1${RESTORE} ${BOLD}${LPURPLE}====${RESTORE}"
57 | }
58 |
59 | echoHelp ()
60 | {
61 | echo "${BOLD}$1${RESTORE}: ${GREEN}$2${RESTORE}"
62 | }
63 |
--------------------------------------------------------------------------------
/scripts/pumltoimages.bash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | BASEDIR=$(dirname $0)
4 | PUML="java -jar ${BASEDIR}/../plantuml.jar"
5 |
6 | $PUML -o images/puml docs/*.puml
7 |
--------------------------------------------------------------------------------
/scripts/runtests.bash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | BASEDIR=$(dirname $0)
4 | PHP="env php "
5 | source ${BASEDIR}/functions
6 | PROJECTDIR="${BASEDIR}/../"
7 |
8 | cd ${PROJECTDIR}
9 |
10 | if [ $# -eq 0 ] || [ "$1" == "unit" ]; then
11 | echoTitle "PHPUNIT Tests"
12 | $PHP ./vendor/bin/phpunit -c tests/ --exclude-group behat
13 | fi
14 |
15 | if [ $# -eq 0 ]; then
16 | echo ""
17 | echo "***************"
18 | echo ""
19 | fi
20 |
21 | if [ $# -eq 0 ] || [ "$1" == "behat" ]; then
22 | echoTitle "BEHAT Test"
23 | $PHP ./vendor/bin/behat -c tests/behat.yml
24 | fi
25 |
26 | echoSuccess "Done."
27 | exit 0;
28 |
--------------------------------------------------------------------------------
/scripts/travis_deploy.bash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Unpack secrets; -C ensures they unpack *in* the .travis directory
4 | tar xvf .travis/secrets.tar -C .travis
5 |
6 | # Setup SSH agent:
7 | eval "$(ssh-agent -s)" #start the ssh agent
8 | chmod 600 .travis/build-key.pem
9 | ssh-add .travis/build-key.pem
10 |
11 | # Setup git defaults:
12 | git config --global user.email "github-ezlaunchpad@ez.no"
13 | git config --global user.name "eZ Launchpad Github Bot"
14 |
15 | # Add SSH-based remote to GitHub repo:
16 | git remote add deploy git@github.com:ezsystems/launchpad.git
17 | git fetch deploy
18 | git checkout master
19 | git status
20 |
21 | # Get box and build PHAR
22 | curl -LSs https://box-project.github.io/box2/installer.php | php
23 | chmod 755 box.phar
24 |
25 | composer install --no-dev
26 |
27 | # Build the box
28 | ./box.phar build -vv
29 |
30 | # Generate the PHAR
31 | sha1sum ez.phar > docs/ez.phar.version
32 | mv ez.phar docs/ez.phar
33 | git add docs/ez.phar docs/ez.phar.version
34 |
35 | # Commit and push:
36 | DATED_SUFFIX=`date +%Y-%m-%d-%H-%M-%S`
37 | git commit -m "[skip ci] Deployment new eZ Launchpad on $DATED_SUFFIX"
38 | git push deploy master
39 |
--------------------------------------------------------------------------------
/src/Command/Docker/Build.php:
--------------------------------------------------------------------------------
1 | setName('docker:build')->setDescription('Build all the services (or just one).');
23 | $this->addArgument('service', InputArgument::OPTIONAL, 'Service to build', '');
24 | $this->setAliases(['build']);
25 | }
26 |
27 | protected function execute(InputInterface $input, OutputInterface $output): int
28 | {
29 | $this->dockerClient->build([], $input->getArgument('service'));
30 | $this->taskExecutor->composerInstall();
31 |
32 | return DockerCommand::SUCCESS;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/Command/Docker/Clean.php:
--------------------------------------------------------------------------------
1 | setName('docker:clean')->setDescription('Clean all the services.');
22 | $this->setAliases(['docker:down', 'clean', 'down']);
23 | }
24 |
25 | protected function execute(InputInterface $input, OutputInterface $output): int
26 | {
27 | $this->dockerClient->down(['-v', '--remove-orphans']);
28 |
29 | return DockerCommand::SUCCESS;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Command/Docker/ComposerRun.php:
--------------------------------------------------------------------------------
1 | setName('docker:comprun')->setDescription('Run Composer command in the engine.');
23 | $this->setAliases(['comprun']);
24 | $this->addArgument(
25 | 'compcommand',
26 | InputArgument::IS_ARRAY,
27 | 'Composer Command to run in. Use "" to pass options.'
28 | );
29 | }
30 |
31 | protected function execute(InputInterface $input, OutputInterface $output): int
32 | {
33 | $allArguments = $input->getArgument('compcommand');
34 | $options = '';
35 | $this->taskExecutor->runComposerCommand(implode(' ', $allArguments)." {$options}");
36 |
37 | return DockerCommand::SUCCESS;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/Command/Docker/Create.php:
--------------------------------------------------------------------------------
1 | projectStatusDumper = $projectStatusDumper;
28 | }
29 |
30 | protected function configure(): void
31 | {
32 | parent::configure();
33 | $this->setName('docker:create')->setDescription('Create all the services.');
34 | $this->setAliases(['create']);
35 | }
36 |
37 | protected function initialize(InputInterface $input, OutputInterface $output): void
38 | {
39 | parent::initialize($input, $output);
40 | $this->projectStatusDumper->setDockerClient($this->dockerClient);
41 | $this->projectStatusDumper->setIo($this->io);
42 | }
43 |
44 | protected function execute(InputInterface $input, OutputInterface $output): int
45 | {
46 | $this->dockerClient->build(['--no-cache']);
47 | $this->dockerClient->up(['-d']);
48 |
49 | $this->taskExecutor->composerInstall();
50 | $this->taskExecutor->eZCreate();
51 | $this->taskExecutor->importData();
52 |
53 | // if solr run the index
54 | $compose = $this->projectConfiguration->getDockerCompose();
55 | if ($compose->hasService('solr')) {
56 | $this->taskExecutor->createCore();
57 | $this->taskExecutor->indexSolr();
58 | }
59 |
60 | $this->projectStatusDumper->dump('ncsi');
61 |
62 | return DockerCommand::SUCCESS;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/Command/Docker/DumpData.php:
--------------------------------------------------------------------------------
1 | setName('docker:dumpdata')->setDescription('Dump Database and Storage.');
22 | $this->setAliases(['dumpdata']);
23 | }
24 |
25 | protected function execute(InputInterface $input, OutputInterface $output): int
26 | {
27 | $this->taskExecutor->dumpData();
28 |
29 | return DockerCommand::SUCCESS;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Command/Docker/Enter.php:
--------------------------------------------------------------------------------
1 | setName('docker:enter')->setDescription('Enter in a container.');
24 | $this->addArgument('service', InputArgument::OPTIONAL, 'Service to enter in', 'engine');
25 | $this->addOption('user', 'u', InputOption::VALUE_REQUIRED, 'User with who to enter in', 'www-data');
26 | $this->addArgument('shell', InputArgument::OPTIONAL, 'Command to enter in', '/bin/bash');
27 | $this->setAliases(['enter', 'docker:exec', 'exec']);
28 | }
29 |
30 | protected function execute(InputInterface $input, OutputInterface $output): int
31 | {
32 | $this->dockerClient->exec(
33 | $input->getArgument('shell'),
34 | [
35 | '--user', $input->getOption('user'),
36 | ],
37 | $input->getArgument('service')
38 | );
39 |
40 | return DockerCommand::SUCCESS;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Command/Docker/ImportData.php:
--------------------------------------------------------------------------------
1 | setName('docker:importdata')->setDescription('Import Database and Storage.');
22 | $this->setAliases(['importdata']);
23 | }
24 |
25 | protected function execute(InputInterface $input, OutputInterface $output): int
26 | {
27 | $this->taskExecutor->importData();
28 |
29 | return DockerCommand::SUCCESS;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Command/Docker/InitializeSkeleton.php:
--------------------------------------------------------------------------------
1 | setName('docker:initialize:skeleton')->setDescription(
24 | 'Initialize without all of eZ. (REALLY experimental)>'
25 | );
26 | $this->setAliases(['docker:init:skeleton', 'init-skeleton']);
27 | $this->setHidden(true);
28 | }
29 |
30 | protected function innerInitialize(
31 | Docker $dockerClient,
32 | DockerCompose $compose,
33 | $composeFilePath,
34 | InputInterface $input
35 | ): void {
36 | $compose->cleanForInitializeSkeleton();
37 | $compose->dump($composeFilePath);
38 |
39 | $fs = new Filesystem();
40 | // Empty Nginx
41 | $nginxEmptyConf = <<dumpFile(
136 | "{$this->projectConfiguration->get('provisioning.folder_name')}/dev/nginx/nginx.conf",
137 | $nginxEmptyConf
138 | );
139 | $fs->dumpFile(
140 | "{$this->projectConfiguration->get('provisioning.folder_name')}/dev/varnish/varnish.conf",
141 | $varnishEmptyConf
142 | );
143 |
144 | $dockerClient->build(['--no-cache']);
145 | $dockerClient->up(['-d']);
146 |
147 | $executor = new TaskExecutor($dockerClient, $this->projectConfiguration, $this->requiredRecipes);
148 | $executor->composerInstall();
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/src/Command/Docker/Logs.php:
--------------------------------------------------------------------------------
1 | setName('docker:logs')->setDescription('Display the logs.');
23 | $this->addArgument('service', InputArgument::OPTIONAL, 'Service to log.', '');
24 | $this->setAliases(['logs', 'log']);
25 | }
26 |
27 | protected function execute(InputInterface $input, OutputInterface $output): int
28 | {
29 | $this->dockerClient->logs(['-f', '--tail=100'], $input->getArgument('service'));
30 |
31 | return DockerCommand::SUCCESS;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Command/Docker/Restart.php:
--------------------------------------------------------------------------------
1 | setName('docker:restart')->setDescription('Restart all the services (or just one).');
21 | $this->addArgument('service', InputArgument::OPTIONAL, 'Service to restart', '');
22 | $this->setAliases(['restart']);
23 | }
24 |
25 | protected function execute(InputInterface $input, OutputInterface $output): int
26 | {
27 | $this->dockerClient->restart($input->getArgument('service'));
28 |
29 | return DockerCommand::SUCCESS;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Command/Docker/Start.php:
--------------------------------------------------------------------------------
1 | setName('docker:start')->setDescription('Start all the services (or just one).');
23 | $this->addArgument('service', InputArgument::OPTIONAL, 'Service to start', '');
24 | $this->setAliases(['start']);
25 | }
26 |
27 | protected function execute(InputInterface $input, OutputInterface $output): int
28 | {
29 | $this->dockerClient->start($input->getArgument('service'));
30 |
31 | return DockerCommand::SUCCESS;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Command/Docker/Status.php:
--------------------------------------------------------------------------------
1 | projectStatusDumper = $projectStatusDumper;
29 | }
30 |
31 | protected function configure(): void
32 | {
33 | parent::configure();
34 | $this->setName('docker:status')->setDescription('Obtaining the project information.');
35 | $this->setAliases(['docker:ps', 'docker:info', 'ps', 'info']);
36 | $this->addArgument(
37 | 'options',
38 | InputArgument::OPTIONAL,
39 | 'n: Docker Network, c: Docker Compose, s: Service Access',
40 | 'ncsz'
41 | );
42 | }
43 |
44 | protected function initialize(InputInterface $input, OutputInterface $output): void
45 | {
46 | parent::initialize($input, $output);
47 | $this->projectStatusDumper->setDockerClient($this->dockerClient);
48 | $this->projectStatusDumper->setIo($this->io);
49 | }
50 |
51 | protected function execute(InputInterface $input, OutputInterface $output): int
52 | {
53 | $this->projectStatusDumper->dump($input->getArgument('options'));
54 |
55 | return DockerCommand::SUCCESS;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Command/Docker/Stop.php:
--------------------------------------------------------------------------------
1 | setName('docker:stop')->setDescription('Stop all the services (or just one).');
23 | $this->addArgument('service', InputArgument::OPTIONAL, 'Service to stop', '');
24 | $this->setAliases(['stop']);
25 | }
26 |
27 | protected function execute(InputInterface $input, OutputInterface $output): int
28 | {
29 | $this->dockerClient->stop($input->getArgument('service'));
30 |
31 | return DockerCommand::SUCCESS;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Command/Docker/SymfonyRun.php:
--------------------------------------------------------------------------------
1 | setName('docker:sfrun')->setDescription('Run a Symfony command in the engine.');
23 | $this->setAliases(['sfrun']);
24 | $this->addArgument('sfcommand', InputArgument::IS_ARRAY, 'Symfony Command to run in. Use "" to pass options.');
25 | }
26 |
27 | protected function execute(InputInterface $input, OutputInterface $output): int
28 | {
29 | $allArguments = $input->getArgument('sfcommand');
30 | $options = '';
31 | $this->taskExecutor->runSymfomyCommand(implode(' ', $allArguments)." {$options}");
32 |
33 | return DockerCommand::SUCCESS;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/Command/Docker/Up.php:
--------------------------------------------------------------------------------
1 | setName('docker:up')->setDescription('Up all the services (or just one).');
23 | $this->addArgument('service', InputArgument::OPTIONAL, 'Service to up', '');
24 | $this->setAliases(['up']);
25 | }
26 |
27 | protected function execute(InputInterface $input, OutputInterface $output): int
28 | {
29 | $this->dockerClient->up(['-d'], $input->getArgument('service'));
30 |
31 | return DockerCommand::SUCCESS;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Command/Docker/Update.php:
--------------------------------------------------------------------------------
1 | setName('docker:update')->setDescription('Update to last images.');
23 | $this->addArgument('service', InputArgument::OPTIONAL, 'Image service to update.', '');
24 | }
25 |
26 | protected function execute(InputInterface $input, OutputInterface $output): int
27 | {
28 | $this->dockerClient->pull(['--ignore-pull-failures'], $input->getArgument('service'));
29 | $this->dockerClient->build([], $input->getArgument('service'));
30 | $this->dockerClient->up(['-d'], $input->getArgument('service'));
31 | $this->taskExecutor->composerInstall();
32 |
33 | return DockerCommand::SUCCESS;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/Command/Platformsh/Deploy.php:
--------------------------------------------------------------------------------
1 | setName('platformsh:deploy')->setDescription('Deploy with Platformsh integration.');
23 | $this->setAliases(['psh:deploy']);
24 | }
25 |
26 | protected function execute(InputInterface $input, OutputInterface $output): int
27 | {
28 | $fs = new Filesystem();
29 | $this->io->title($this->getDescription());
30 |
31 | // add a test to see if folder exists or not
32 | if (!$fs->exists("{$this->projectPath}/.platform")) {
33 | $this->io->error('Your project is not Platformsh ready.');
34 | $this->io->comment('Run ~/ez platformsh:setup to set up the integration.');
35 |
36 | return Command::FAILURE;
37 | }
38 |
39 | $this->io->writeln(
40 | "There is no such thing with Platform.sh.\n".
41 | 'To deploy you just have to git push in the good'.
42 | " remote (usually: platform)\n".
43 | "Automatically Platform.sh will trigger the deployment.\n".
44 | "\nIf you just want to manage one unique git repository have a look: \n".
45 | "\tGithub Integration>:\t https://docs.platform.sh/administration/integrations/github.html\n".
46 | "\tBitbucket Integration>:\t https://docs.platform.sh/administration/integrations/bitbucket.html"
47 | );
48 |
49 | return Command::SUCCESS;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/Command/Platformsh/Setup.php:
--------------------------------------------------------------------------------
1 | setName('platformsh:setup')->setDescription('Set up the Platformsh integration.');
23 | $this->setAliases(['psh:setup']);
24 | }
25 |
26 | protected function postAction(): void
27 | {
28 | $this->io->writeln(
29 | 'You can also look at ~/ez platformsh:deploy.'
30 | );
31 | }
32 |
33 | protected function execute(InputInterface $input, OutputInterface $output): int
34 | {
35 | $fs = new Filesystem();
36 | $this->io->title($this->getDescription());
37 |
38 | // add a test to see if folder exists or not
39 | if ($fs->exists("{$this->projectPath}/.platform")) {
40 | if (!$this->io->confirm('You already have a .platform folder, continue?')) {
41 | $this->postAction();
42 |
43 | return DockerCommand::FAILURE;
44 | }
45 | }
46 |
47 | // Dump the project
48 | $this->taskExecutor->dumpData();
49 |
50 | // move it to the top folder as required my Platform.sh
51 | $fs->rename("{$this->projectPath}/ezplatform/.platform", "{$this->projectPath}/.platform");
52 |
53 | $this->io->writeln(
54 | "Your project is now set up with Platform.sh.\n".
55 | "You can run git status to see the changes\n".
56 | "Then you just have to \n".
57 | "\tgit add .\n".
58 | "\tgit commit -m \"Integration Platform.sh\"\n".
59 | "\tgit push platform {branchname}\n"
60 | );
61 |
62 | $this->postAction();
63 |
64 | return DockerCommand::SUCCESS;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/Command/SelfUpdate.php:
--------------------------------------------------------------------------------
1 | setName('self-update')->setDescription('Self Update');
28 | }
29 |
30 | public function setParameters(array $parameters = []): void
31 | {
32 | $this->parameters = $parameters;
33 | }
34 |
35 | protected function execute(InputInterface $input, OutputInterface $output): int
36 | {
37 | /* @var Application $application */
38 | $application = $this->getApplication();
39 | $output->writeln($application->getLogo());
40 |
41 | $releaseUrl = $this->parameters['release_url'];
42 | $releases = githubFetch($releaseUrl);
43 | if (null === $releases) {
44 | $this->io->comment('Cannot find new releases, please try later.');
45 |
46 | return Command::FAILURE;
47 | }
48 | $release = $releases[0];
49 | $currentVersion = normalizeVersion($application->getVersion());
50 | $lastVersion = normalizeVersion($release->tag_name);
51 | if ($lastVersion <= $currentVersion) {
52 | $this->io->comment('No update is required! You have the last version!');
53 |
54 | return Command::FAILURE;
55 | }
56 |
57 | $localPharFile = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0];
58 | $localPharDir = \dirname($localPharFile);
59 | $backPharFile = $localPharDir.'/ez.phar.backup';
60 | copy($localPharFile, $backPharFile);
61 | $assetUrl = $release->assets[0]->browser_download_url;
62 | $tempPharFile = $localPharDir.'/ez.phar.temp';
63 | file_put_contents($tempPharFile, githubFetch($assetUrl, false));
64 | copy($localPharFile.'.pubkey', $tempPharFile.'.pubkey');
65 |
66 | $phar = new Phar($tempPharFile);
67 | $signature = $phar->getSignature();
68 | if ('openssl' !== strtolower($signature['hash_type'])) {
69 | $this->io->error('Invalid Signature.');
70 |
71 | return Command::FAILURE;
72 | }
73 | rename($tempPharFile, $localPharFile);
74 | chmod($localPharFile, fileperms($backPharFile));
75 | unlink($tempPharFile.'.pubkey');
76 | $this->io->writeln(
77 | "Updated from {$application->getVersion()} to {$release->tag_name}."
78 | );
79 |
80 | return Command::SUCCESS;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/Configuration/Configuration.php:
--------------------------------------------------------------------------------
1 | getRootNode();
21 | $rootNode
22 | ->children()
23 | ->arrayNode('docker')
24 | ->addDefaultsIfNotSet()
25 | ->children()
26 | ->scalarNode('compose_filename')->defaultValue('docker-compose.yml')->end()
27 | ->scalarNode('network_name')->defaultValue('default-ezlaunchpad')->end()
28 | ->scalarNode('network_prefix_port')->defaultValue(42)->end()
29 | ->scalarNode('host_machine_mapping')->defaultNull()->end()
30 | ->scalarNode('host_composer_cache_dir')->defaultNull()->end()
31 | ->end()
32 | ->end()
33 | ->arrayNode('provisioning')
34 | ->addDefaultsIfNotSet()
35 | ->children()
36 | ->scalarNode('folder_name')->defaultValue('provisioning')->end()
37 | ->end()
38 | ->end()
39 | ->arrayNode('composer')
40 | ->children()
41 | ->arrayNode('http_basic')
42 | ->prototype('array')
43 | ->children()
44 | ->scalarNode('host')->defaultNull()->end()
45 | ->scalarNode('login')->defaultNull()->end()
46 | ->scalarNode('password')->defaultNull()->end()
47 | ->end()
48 | ->end()
49 | ->end()
50 | ->arrayNode('token')
51 | ->prototype('array')
52 | ->children()
53 | ->scalarNode('host')->defaultNull()->end()
54 | ->scalarNode('value')->defaultNull()->end()
55 | ->end()
56 | ->end()
57 | ->end()
58 | ->end()
59 | ->end()
60 | ->scalarNode('last_update_check')->defaultNull()->end()
61 | ->end();
62 |
63 | return $treeBuilder;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/Configuration/Project.php:
--------------------------------------------------------------------------------
1 | globalFilePath = $globalFilePath;
41 | $this->localFilePath = $localFilePath;
42 | $this->configurations = $configurations;
43 | }
44 |
45 | /**
46 | * @return array|mixed|null
47 | */
48 | public function get(string $name)
49 | {
50 | if (strpos($name, '.')) {
51 | $parts = explode('.', $name);
52 | $array = $this->configurations;
53 | foreach ($parts as $part) {
54 | if (!isset($array[$part])) {
55 | return null;
56 | }
57 | $array = $array[$part];
58 | }
59 |
60 | return $array;
61 | }
62 |
63 | return $this->configurations[$name] ?? null;
64 | }
65 |
66 | public function setLocal(string $name, $value): void
67 | {
68 | $this->set([$name => $value], 'local');
69 | }
70 |
71 | public function setGlobal(string $name, $value): void
72 | {
73 | $this->set([$name => $value], 'global');
74 | }
75 |
76 | public function setMultiLocal(array $keyValues): void
77 | {
78 | $this->set($keyValues, 'local');
79 | }
80 |
81 | public function setMultiGlobal(array $keyValues): void
82 | {
83 | $this->set($keyValues, 'global');
84 | }
85 |
86 | public function setEnvironment(string $environment): void
87 | {
88 | $this->environment = $environment;
89 | }
90 |
91 | /**
92 | * Store inMemory and in the good file.
93 | */
94 | protected function set(array $keyValues, string $where = 'global'): void
95 | {
96 | $filePath = 'global' === $where ? $this->globalFilePath : $this->localFilePath;
97 |
98 | $fs = new Filesystem();
99 | $config = $fs->exists($filePath) ? Yaml::parse(file_get_contents($filePath)) : [];
100 |
101 | foreach ($keyValues as $name => $value) {
102 | if (strpos($name, '.')) {
103 | $parts = explode('.', $name);
104 | $onFile = &$config;
105 | foreach ($parts as $part) {
106 | $onFile = &$onFile[$part];
107 | }
108 | $onFile = $value;
109 |
110 | $inMemory = &$this->configurations;
111 |
112 | foreach ($parts as $part) {
113 | $inMemory = &$inMemory[$part];
114 | }
115 | $inMemory = $value;
116 | } else {
117 | $this->configurations[$name] = $value;
118 | $config[$name] = $value;
119 | }
120 | }
121 |
122 | $yaml = Yaml::dump($config, 4);
123 | $fs->dumpFile($filePath, $yaml);
124 | }
125 |
126 | public function getDockerCompose(): DockerCompose
127 | {
128 | $projectPath = \dirname($this->localFilePath);
129 |
130 | return new DockerCompose(
131 | "{$projectPath}/"."{$this->get('provisioning.folder_name')}/".
132 | "{$this->environment}/{$this->get('docker.compose_filename')}"
133 | );
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/Console/Application.php:
--------------------------------------------------------------------------------
1 |
40 | *>
41 | *> *>
42 | ___>
43 | | | |>
44 | *> / \ | |>
45 | |--o>|===>|>->|>
46 | |--->| | |>
47 | *> / \ | |>
48 | | eZ> | | |>
49 | | |=>| |>
50 | Launchpad> | |>
51 | |_______| |_>|>
52 | |@>| |@>| | |>
53 | ____\|/___________>|>_>|>_>
54 |
55 | >';
56 |
57 | /**
58 | * @var ContainerBuilder
59 | */
60 | protected $container;
61 |
62 | public function setContainer(ContainerBuilder $container): self
63 | {
64 | $this->container = $container;
65 |
66 | return $this;
67 | }
68 |
69 | public function setEnv(string $env): self
70 | {
71 | $this->env = $env;
72 |
73 | return $this;
74 | }
75 |
76 | public function getLogo(): string
77 | {
78 | return self::$logo.$this->getLongVersion();
79 | }
80 |
81 | public function getHelp(): string
82 | {
83 | return self::$logo.parent::getHelp();
84 | }
85 |
86 | public function run(InputInterface $input = null, OutputInterface $output = null): int
87 | {
88 | // configure styles here
89 | return parent::run($input, $output);
90 | }
91 |
92 | public function doRun(InputInterface $input, OutputInterface $output): int
93 | {
94 | $this->loadConfiguration($input);
95 |
96 | // add the command from the configuration
97 | $commands = $this->container->findTaggedServiceIds('ezlaunchpad.command');
98 | foreach ($commands as $def => $values) {
99 | $command = $this->container->get($def);
100 | if ($command instanceof Core\Command) {
101 | $this->add($command);
102 | }
103 | }
104 |
105 | return parent::doRun($input, $output);
106 | }
107 |
108 | protected function loadConfiguration(InputInterface $input): void
109 | {
110 | $appDir = __DIR__.'/../../';
111 | $projectPath = getcwd();
112 | $this->container->setParameter('app_dir', $appDir);
113 | $this->container->setParameter('app_env', $this->env);
114 | $this->container->setParameter('project_path', $projectPath);
115 |
116 | // Override the defaults values
117 | $globalFilePath = $input->getParameterOption(['--config', '-c'], EZ_HOME.'/ez.yml');
118 | $fs = new Filesystem();
119 | $configs = [];
120 |
121 | if ($fs->exists($globalFilePath)) {
122 | $configs[] = Yaml::parse(file_get_contents($globalFilePath));
123 | } else {
124 | if ($input->hasParameterOption(['--config', '-c'])) {
125 | throw new FileNotFoundException("Configuraton file {$globalFilePath} not found.");
126 | }
127 | }
128 |
129 | // Load the local values and OVERRIDE
130 | $localFilePath = $projectPath.'/.ezlaunchpad.yml';
131 | if ($fs->exists($localFilePath)) {
132 | $configs[] = Yaml::parse(file_get_contents($localFilePath));
133 | }
134 | $processor = new Processor();
135 | $configuration = new Configuration();
136 | $processedConfiguration = $processor->processConfiguration(
137 | $configuration,
138 | $configs
139 | );
140 |
141 | // set the dispatcher
142 | $this->container->setDefinition(
143 | 'event_dispatcher',
144 | (new Definition(EventDispatcher::class))->setPublic(true)
145 | );
146 |
147 | // set the project configuration service
148 | $this->container->setDefinition(
149 | ProjectConfiguration::class,
150 | (new Definition(
151 | ProjectConfiguration::class,
152 | [
153 | $globalFilePath,
154 | $localFilePath,
155 | $processedConfiguration,
156 | ]
157 | ))->setPublic(true)
158 | );
159 | // Compile
160 | $this->compileConfiguration();
161 | }
162 |
163 | /**
164 | * Find and compile the configuration.
165 | */
166 | protected function compileConfiguration(): void
167 | {
168 | $this->container->compile();
169 | $eventDispatcher = $this->container->get('event_dispatcher');
170 | if ($eventDispatcher instanceof EventDispatcherInterface) {
171 | $this->setDispatcher(
172 | $eventDispatcher
173 | );
174 | }
175 | }
176 |
177 | protected function getDefaultInputDefinition(): InputDefinition
178 | {
179 | $definition = parent::getDefaultInputDefinition();
180 | $definition->addOption(
181 | new InputOption(
182 | '--config',
183 | '-c',
184 | InputOption::VALUE_REQUIRED,
185 | 'use the given file as configuration file, instead of the default one ('.EZ_HOME.'/ez.yml'.').'
186 | )
187 | );
188 |
189 | return $definition;
190 | }
191 | }
192 |
--------------------------------------------------------------------------------
/src/Console/ApplicationFactory.php:
--------------------------------------------------------------------------------
1 | addCompilerPass(new CommandPass($env));
30 | $container->addCompilerPass(new RegisterListenersPass());
31 | $loader = new YamlFileLoader($container, new FileLocator(__DIR__));
32 | $loader->load(__DIR__.'/../../config/services.yml');
33 | $loader->load(__DIR__.'/../../config/commands.yml');
34 | $application = new Console\Application();
35 | $application->setContainer($container);
36 | $application->setEnv($env);
37 | $application->setName('eZ Launchpad');
38 | $application->setVersion('@package_version@'.(('prod' !== $env) ? '-dev' : ''));
39 | $application->setAutoExit($autoExit);
40 |
41 | return $application;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Core/Command.php:
--------------------------------------------------------------------------------
1 | io = new SymfonyStyle($input, $output);
55 | }
56 |
57 | public function setProjectConfiguration(ProjectConfiguration $configuration): self
58 | {
59 | $this->projectConfiguration = $configuration;
60 |
61 | return $this;
62 | }
63 |
64 | public function setAppDir(string $appDir): void
65 | {
66 | $this->appDir = $appDir;
67 | }
68 |
69 | public function getPayloadDir(): string
70 | {
71 | return "{$this->appDir}payload";
72 | }
73 |
74 | public function setProjectPath(string $projectPath): void
75 | {
76 | $this->projectPath = $projectPath;
77 | }
78 |
79 | public function getProjectPath(): string
80 | {
81 | return $this->projectPath;
82 | }
83 |
84 | public function setRequiredRecipes(array $requiredRecipes): void
85 | {
86 | $this->requiredRecipes = NovaCollection($requiredRecipes);
87 | }
88 |
89 | public function getRequiredRecipes(): Collection
90 | {
91 | if (null === $this->requiredRecipes) {
92 | $this->requiredRecipes = NovaCollection([]);
93 | }
94 |
95 | return $this->requiredRecipes;
96 | }
97 |
98 | public function setOptimizer(OptimizerInterface $optimizer): void
99 | {
100 | $this->optimizer = $optimizer;
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/Core/DockerCommand.php:
--------------------------------------------------------------------------------
1 | addOption('env', 'e', InputOption::VALUE_REQUIRED, 'The Environment name.', 'dev');
39 | $this->addOption(
40 | 'docker-env',
41 | 'd',
42 | InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
43 | 'Docker environment variables',
44 | []
45 | );
46 | }
47 |
48 | public function getDockerClient(): Docker
49 | {
50 | return $this->dockerClient;
51 | }
52 |
53 | protected function initialize(InputInterface $input, OutputInterface $output): void
54 | {
55 | parent::initialize($input, $output);
56 | $this->environment = $input->getOption('env');
57 | $this->projectConfiguration->setEnvironment($this->environment);
58 | $fs = new Filesystem();
59 | $currentPwd = $this->projectPath;
60 | $provisioningFolder = $this->projectConfiguration->get('provisioning.folder_name');
61 | $dockerComposeFileName = $this->projectConfiguration->get('docker.compose_filename');
62 | $dockerComposeFileFolder = NovaCollection([$currentPwd, $provisioningFolder, $this->environment])->implode(
63 | '/'
64 | );
65 |
66 | if (!$fs->exists($dockerComposeFileFolder."/{$dockerComposeFileName}")) {
67 | throw new RuntimeException("There is no {$dockerComposeFileName} in {$dockerComposeFileFolder}");
68 | }
69 | $options = [
70 | 'compose-file' => $dockerComposeFileFolder."/{$dockerComposeFileName}",
71 | 'network-name' => $this->projectConfiguration->get('docker.network_name'),
72 | 'network-prefix-port' => $this->projectConfiguration->get('docker.network_prefix_port'),
73 | 'host-machine-mapping' => $this->projectConfiguration->get('docker.host_machine_mapping'),
74 | 'project-path' => $this->projectPath,
75 | 'provisioning-folder-name' => $provisioningFolder,
76 | 'composer-cache-dir' => $this->projectConfiguration->get('docker.host_composer_cache_dir'),
77 | ];
78 |
79 | $this->dockerClient = new Docker($options, new ProcessRunner(), $this->optimizer);
80 | $this->taskExecutor = new TaskExecutor(
81 | $this->dockerClient,
82 | $this->projectConfiguration,
83 | $this->requiredRecipes,
84 | $input->getOption('docker-env')
85 | );
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/Core/DockerCompose.php:
--------------------------------------------------------------------------------
1 | compose = Yaml::parse(file_get_contents($filePath));
23 | }
24 |
25 | public function getServices(): array
26 | {
27 | return $this->compose['services'];
28 | }
29 |
30 | public function hasService(string $name): bool
31 | {
32 | return isset($this->compose['services'][$name]);
33 | }
34 |
35 | public function dump(string $destination): void
36 | {
37 | $yaml = Yaml::dump($this->compose, 4);
38 | $fs = new Filesystem();
39 | $fs->dumpFile($destination, $yaml);
40 | }
41 |
42 | public function filterServices(array $selectedServices): void
43 | {
44 | $services = [];
45 | foreach ($this->getServices() as $name => $service) {
46 | if (!\in_array($name, $selectedServices)) {
47 | continue;
48 | }
49 | $services[$name] = $service;
50 | }
51 | $this->compose['services'] = $services;
52 | }
53 |
54 | public function cleanForInitializeSkeleton(): void
55 | {
56 | $services = [];
57 | foreach ($this->getServices() as $name => $service) {
58 | // Solr is not managed here
59 | if ('solr' === $name) {
60 | continue;
61 | }
62 |
63 | if (isset($service['volumes'])) {
64 | $volumes = NovaCollection($service['volumes']);
65 | $service['volumes'] = $volumes->prune(
66 | function ($value) {
67 | return false === strpos($value, 'ezplatform');
68 | }
69 | )->toArray();
70 | }
71 | $services[$name] = $service;
72 | }
73 | $this->compose['services'] = $services;
74 | }
75 |
76 | public function cleanForInitialize(): void
77 | {
78 | $services = [];
79 | foreach ($this->getServices() as $name => $service) {
80 | // we don't need anything else for the init
81 | if (!\in_array($name, ['engine', 'db'])) {
82 | continue;
83 | }
84 |
85 | if (isset($service['volumes'])) {
86 | $volumes = NovaCollection($service['volumes']);
87 | $service['volumes'] = $volumes->prune(
88 | function ($value) {
89 | return false === strpos($value, 'ezplatform');
90 | }
91 | )->toArray();
92 | }
93 | if (isset($service['environment'])) {
94 | $environnementVars = NovaCollection($service['environment']);
95 | $service['environment'] = $environnementVars->prune(
96 | function ($value) {
97 | $vars = [
98 | 'CUSTOM_CACHE_POOL',
99 | 'CACHE_HOST',
100 | 'CACHE_REDIS_PORT',
101 | 'CACHE_POOL',
102 | 'CACHE_DSN',
103 | 'SEARCH_ENGINE',
104 | 'SOLR_DSN',
105 | 'HTTPCACHE_PURGE_SERVER',
106 | 'SYMFONY_TMP_DIR',
107 | ];
108 |
109 | return !preg_match(
110 | '/('.implode('|', $vars).')/',
111 | $value
112 | );
113 | }
114 | )->values()->toArray();
115 | }
116 | $services[$name] = $service;
117 | }
118 | $this->compose['services'] = $services;
119 | }
120 |
121 | public function removeUselessEnvironmentsVariables(): void
122 | {
123 | $services = [];
124 | foreach ($this->getServices() as $name => $service) {
125 | if (isset($service['environment'])) {
126 | $environnementVars = NovaCollection($service['environment']);
127 | $service['environment'] = $environnementVars->prune(
128 | function ($value) {
129 | if (!$this->hasService('solr')) {
130 | if (preg_match('/(SEARCH_ENGINE|SOLR_DSN)/', $value)) {
131 | return false;
132 | }
133 | }
134 | if (!$this->hasService('redis')) {
135 | if (
136 | preg_match(
137 | '/(CUSTOM_CACHE_POOL|CACHE_HOST|CACHE_POOL|CACHE_DSN|CACHE_REDIS_PORT)/',
138 | $value
139 | )
140 | ) {
141 | return false;
142 | }
143 | }
144 | if (!$this->hasService('varnish')) {
145 | if (preg_match('/(HTTPCACHE_PURGE_SERVER)/', $value)) {
146 | return false;
147 | }
148 | }
149 |
150 | return true;
151 | }
152 | )->values()->toArray();
153 | }
154 | $services[$name] = $service;
155 | }
156 | $this->compose['services'] = $services;
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/src/Core/OSX/Optimizer/D4M.php:
--------------------------------------------------------------------------------
1 | getHostMapping();
25 | MacOSPatherize($export);
26 |
27 | return $this->isResvReady() && $this->isExportReady($export) && self::isD4MScreenExist();
28 | }
29 |
30 | public function hasPermission(SymfonyStyle $io): bool
31 | {
32 | list($export, $mountPoint) = $this->getHostMapping();
33 | MacOSPatherize($export);
34 |
35 | $exportLine = "{$export} {$this->getExportOptions()}";
36 |
37 | $this->standardNFSConfigurationMessage($io, $exportLine);
38 | $io->comment(
39 | "
40 | - Communicate with the Docker Moby VM and add the mount point
41 | {$export} -> {$mountPoint}
42 | "
43 | );
44 |
45 | return $io->confirm('Do you want to setup your Mac as an NFS server and wire the MobbyVM through a screen?');
46 | }
47 |
48 | public function getExportOptions(): string
49 | {
50 | return '-mapall='.getenv('USER').':staff localhost';
51 | }
52 |
53 | public function optimize(SymfonyStyle $io, Command $command): bool
54 | {
55 | $isD4MScreenExist = self::isD4MScreenExist();
56 | $this->setupNFS($io, $this->getExportOptions());
57 | list($export, $mountPoint) = $this->getHostMapping();
58 | MacOSPatherize($export);
59 | if (!$isD4MScreenExist) {
60 | $screenInit = 'screen -AmdS '.static::SCREEN_NAME;
61 | $screen = 'screen -S '.static::SCREEN_NAME.' -p 0 -X stuff';
62 | $mountOptions = 'nolock,local_lock=all';
63 | $mount = "mount -o {$mountOptions} \\$(route|awk '/default/ {print \\$2}'):{$export} {$mountPoint}";
64 | $mobyTTY = '~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/tty';
65 |
66 | exec("{$screenInit} {$mobyTTY}");
67 | exec($screen.' $(printf "root\\r\\n")');
68 | $commands = [
69 | 'sleep 2',
70 | 'apk add --update nfs-utils',
71 | "mkdir -p {$mountPoint}",
72 | 'rpcbind -s',
73 | 'sleep 2',
74 | $mount,
75 | ];
76 | $cmd = implode(' && ', $commands);
77 | exec($screen.' "'.$cmd.PHP_EOL.'"');
78 | sleep(5);
79 |
80 | if (!self::isD4MScreenExist()) {
81 | $message = static::SCREEN_NAME.'screen failed to initiate. Mount point will not be ready.';
82 | throw new RuntimeException($message);
83 | }
84 | $io->success('Moby VM mount succeed.');
85 | }
86 |
87 | return true;
88 | }
89 |
90 | public static function isD4MScreenExist(): bool
91 | {
92 | $output = $return = null;
93 | exec('screen -list | grep -q "'.static::SCREEN_NAME.'";', $output, $return);
94 |
95 | return 0 === $return;
96 | }
97 |
98 | public function supports(int $version): bool
99 | {
100 | return $version < 1712;
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/Core/OSX/Optimizer/NFSAwareInterface.php:
--------------------------------------------------------------------------------
1 | success('NFSD restarted.');
26 |
27 | return true;
28 | }
29 |
30 | public function getHostMapping(): array
31 | {
32 | $default = [getenv('HOME'), getenv('HOME')];
33 |
34 | $currentMapping = $this->projectConfiguration->get('docker.host_machine_mapping');
35 | if ($currentMapping) {
36 | return explode(':', $currentMapping);
37 | }
38 | $this->projectConfiguration->setGlobal('docker.host_machine_mapping', implode(':', $default));
39 |
40 | return $default;
41 | }
42 |
43 | public function isExportReady($export): bool
44 | {
45 | $fs = new Filesystem();
46 | if (!$fs->exists(NFSAwareInterface::EXPORTS)) {
47 | return false;
48 | }
49 |
50 | return NovaCollection(file(NFSAwareInterface::EXPORTS))->exists(
51 | function ($line) use ($export) {
52 | $export = addcslashes($export, '/.');
53 |
54 | $line = trim($line);
55 |
56 | return 1 === preg_match("#^{$export}#", $line);
57 | }
58 | );
59 | }
60 |
61 | public function isResvReady(): bool
62 | {
63 | $fs = new Filesystem();
64 | if (!$fs->exists(NFSAwareInterface::RESV)) {
65 | return false;
66 | }
67 |
68 | return NovaCollection(file(NFSAwareInterface::RESV))->exists(
69 | function ($line) {
70 | $line = trim($line);
71 | if (preg_match("/^nfs\.server\.mount\.require_resv_port/", $line)) {
72 | if (strpos($line, '=')) {
73 | return '0' == trim(explode('=', $line)[1]);
74 | }
75 | }
76 |
77 | return false;
78 | }
79 | );
80 | }
81 |
82 | public function setupNFS(SymfonyStyle $io, $exportOptions): bool
83 | {
84 | list($export, $mountPoint) = $this->getHostMapping();
85 | $export = MacOSPatherize($export);
86 |
87 | $isResvReady = $this->isResvReady();
88 | $isExportReady = $this->isExportReady($export);
89 |
90 | if (!$isResvReady) {
91 | exec(
92 | 'echo "nfs.server.mount.require_resv_port = 0" | sudo tee -a '.NFSAwareInterface::RESV,
93 | $output,
94 | $returnCode
95 | );
96 | if (0 != $returnCode) {
97 | throw new RuntimeException('Writing in '.NFSAwareInterface::RESV.' failed.');
98 | }
99 | $io->success(NFSAwareInterface::RESV.' updated.');
100 | if (!$this->restartNFSD($io)) {
101 | return false;
102 | }
103 | }
104 |
105 | if (!$isExportReady) {
106 | $output = $returnCode = null;
107 | $exportLine = "{$export} {$exportOptions}";
108 | exec("echo \"{$exportLine}\" | sudo tee -a ".NFSAwareInterface::EXPORTS, $output, $returnCode);
109 | if (0 != $returnCode) {
110 | throw new RuntimeException('Writing in '.NFSAwareInterface::EXPORTS.' failed.');
111 | }
112 | $io->success(NFSAwareInterface::EXPORTS.' updated.');
113 | if (!$this->restartNFSD($io)) {
114 | return false;
115 | }
116 | }
117 |
118 | return true;
119 | }
120 |
121 | public function standardNFSConfigurationMessage(SymfonyStyle $io, $exportLine): void
122 | {
123 | $io->caution('You are on Mac OS X, for optimal performance we recommend to mount the host through NFS.');
124 | $io->comment(
125 | "
126 | This wizard is going to check and to do this step if required:
127 | - Add {$exportLine} in ".NFSAwareInterface::EXPORTS.'
128 | - Add nfs.server.mount.require_resv_port = 0 in '.NFSAwareInterface::RESV.'
129 | - Add restart your nfsd server: nfsd restart
130 | '
131 | );
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/src/Core/OSX/Optimizer/NFSVolumes.php:
--------------------------------------------------------------------------------
1 | getHostMapping();
22 | $export = MacOSPatherize($export);
23 |
24 | return $this->isResvReady() && $this->isExportReady($export);
25 | }
26 |
27 | public function hasPermission(SymfonyStyle $io): bool
28 | {
29 | list($export, $mountPoint) = $this->getHostMapping();
30 | $export = MacOSPatherize($export);
31 | $exportLine = "{$export} {$this->getExportOptions()}";
32 | $this->standardNFSConfigurationMessage($io, $exportLine);
33 |
34 | return $io->confirm('Do you want to setup your Mac as an NFS server?');
35 | }
36 |
37 | public function getExportOptions(): string
38 | {
39 | return '-mapall='.getenv('USER').':staff -alldirs localhost';
40 | }
41 |
42 | public function optimize(SymfonyStyle $io, Command $command): bool
43 | {
44 | $this->setupNFS($io, $this->getExportOptions());
45 |
46 | return true;
47 | }
48 |
49 | public function supports($version): bool
50 | {
51 | return $version >= 1803;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/Core/OSX/Optimizer/Optimizer.php:
--------------------------------------------------------------------------------
1 | projectConfiguration = $configuration;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Core/OSX/Optimizer/OptimizerInterface.php:
--------------------------------------------------------------------------------
1 | setTimeout(2 * 3600);
24 |
25 | if ($this->hasTty()) {
26 | $process->setTty(true);
27 | }
28 |
29 | try {
30 | return $process->mustRun();
31 | } catch (ProcessFailedException $e) {
32 | $authorizedExitCodes = [
33 | 129, // Hangup
34 | 130, // Interrupt
35 | ];
36 |
37 | if (!\in_array($e->getProcess()->getExitCode(), $authorizedExitCodes)) {
38 | throw $e;
39 | }
40 | }
41 |
42 | return null;
43 | }
44 |
45 | public function hasTty(): bool
46 | {
47 | // Extracted from \Symfony\Component\Process\Process::setTty
48 | if ('\\' === \DIRECTORY_SEPARATOR) {
49 | // Windows platform does not have TTY
50 | $isTtySupported = false;
51 | } else {
52 | $pipes = null;
53 | // TTY mode requires /dev/tty to be read/writable.
54 | $isTtySupported = (bool) @proc_open(
55 | 'echo 1 >/dev/null',
56 | [
57 | ['file', '/dev/tty', 'r'],
58 | ['file', '/dev/tty', 'w'],
59 | ['file', '/dev/tty', 'w'],
60 | ],
61 | $pipes
62 | );
63 | }
64 |
65 | return $isTtySupported;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/Core/ProjectStatusDumper.php:
--------------------------------------------------------------------------------
1 | projectConfiguration = $projectConfiguration;
37 | }
38 |
39 | public function setDockerClient(Docker $dockerClient): void
40 | {
41 | $this->dockerClient = $dockerClient;
42 | }
43 |
44 | public function setIo(SymfonyStyle $io): void
45 | {
46 | $this->io = $io;
47 | }
48 |
49 | /**
50 | * @param Collection|string|array $options
51 | */
52 | public function dump($options): void
53 | {
54 | if (\is_string($options)) {
55 | $options = str_split($options);
56 | }
57 | if (\is_array($options)) {
58 | $options = NovaCollection($options);
59 | }
60 | if ($options->contains('n')) {
61 | $this->dumpNetwork();
62 | }
63 | if ($options->contains('c')) {
64 | $this->dumpComposeCommand();
65 | }
66 |
67 | if ($options->contains('i')) {
68 | $this->dumpFirstTime();
69 | }
70 | if ($options->contains('s')) {
71 | $this->dumpServiceAccess();
72 | }
73 | }
74 |
75 | protected function dumpNetwork(): void
76 | {
77 | $this->io->title('Docker Network');
78 | $this->dockerClient->ps();
79 | }
80 |
81 | protected function dumpComposeCommand(): void
82 | {
83 | $composeCommand = $this->dockerClient->getComposeCommand();
84 | $this->io->title("\nDocker Compose command");
85 | $this->io->writeln($composeCommand);
86 | }
87 |
88 | /**
89 | * Dump Human service acccess.
90 | */
91 | protected function dumpServiceAccess(): void
92 | {
93 | $portPrefix = $this->projectConfiguration->get('docker.network_prefix_port');
94 | $dump = function ($title, $port, $suffix = '', $proto = 'http') use ($portPrefix) {
95 | $this->io->writeln(
96 | "{$title}: >".
97 | str_pad('', 1, "\t").
98 | "{$proto}://localhost:{$portPrefix}{$port}>{$suffix}"
99 | );
100 | };
101 | $this->io->title('Service Access');
102 |
103 | $adminURI = '/ez';
104 | if ($this->dockerClient->isEzPlatform2x()) {
105 | $adminURI = '/admin';
106 | }
107 | $services = $this->projectConfiguration->getDockerCompose()->getServices();
108 | if (isset($services['nginx'])) {
109 | $this->io->section('Project Web Access');
110 | $dump('Nginx - Front-end (Development Mode)', '080');
111 | $dump('Nginx - Back-end (Development Mode)', '080', $adminURI);
112 |
113 | if (isset($services['varnish'])) {
114 | $dump('Varnish - Front-end (Production Mode)', '082');
115 | $dump('Varnish - Back-end (Production Mode)', '082', $adminURI);
116 | } else {
117 | $dump('Nginx - Front-end (Production Mode)', '081');
118 | $dump('Nginx - Back-end (Production Mode)', '081', $adminURI);
119 | }
120 | }
121 |
122 | if (isset($services['db'])) {
123 | $this->io->section('Database Access');
124 | $dump('MariaDB', '306', '', 'tcp');
125 | }
126 |
127 | if (isset($services['solr'])) {
128 | $this->io->section('Solr Access');
129 | $dump('Solr', '983');
130 | }
131 |
132 | if (isset($services['mailcatcher']) || isset($services['adminer']) || isset($services['redisadmin'])) {
133 | $this->io->section('Tools');
134 | if (isset($services['mailcatcher'])) {
135 | $dump('Mailcatcher', '180');
136 | }
137 | if (isset($services['adminer'])) {
138 | $dump('Adminer', '084');
139 | }
140 | if (isset($services['redisadmin'])) {
141 | $dump('Redis Admin', '083');
142 | }
143 | }
144 | }
145 |
146 | /**
147 | * Dump first time stuff.
148 | */
149 | protected function dumpFirstTime(): void
150 | {
151 | $this->io->title("\033[2J\033[0;0HWelcome in eZ Launchpad!");
152 | $this->io->writeln(
153 | "Your project environment is now up and running. You have eZ Platform installed and running.\n".
154 | 'All the information are define in the section Service Access below.'
155 | );
156 |
157 | $this->io->section('Code and CVS');
158 | $this->io->writeln(
159 | "You will find the folder ezplatform which contains eZ Platform.\n".
160 | "The provisioning folder contains your local stack specifics.\n".
161 | ".gitignore have been provided then you can commit everything right now.\n"
162 | );
163 |
164 | $this->io->section('Dump and storage');
165 | $this->io->writeln(
166 | "Once intialized you can dump the database and the storage to include it in your repository.\n".
167 | '~ez dumpdata will create a data folder containing'.
168 | ' an archive for each (db.sql.gz and storage.tar.gz).'
169 | );
170 |
171 | $this->io->section('Sharing');
172 | $this->io->writeln(
173 | "Once commited and pushed, your collaborators can just git pull to get the project\n".
174 | "And then run ~/ez create to duplicate the environment.\n"
175 | );
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/src/Core/TaskExecutor.php:
--------------------------------------------------------------------------------
1 | dockerClient = $dockerClient;
47 | $this->projectConfiguration = $configuration;
48 | $this->recipes = $recipes;
49 | $this->dockerEnvVars = $dockerEnvVars;
50 | }
51 |
52 | protected function checkRecipeAvailability(string $recipe): void
53 | {
54 | if (!$this->recipes->contains($recipe)) {
55 | throw new RuntimeException("Recipe {$recipe} is not available.");
56 | }
57 | }
58 |
59 | /**
60 | * @return Process[]
61 | */
62 | public function composerInstall(): array
63 | {
64 | $recipe = 'composer_install';
65 | $this->checkRecipeAvailability($recipe);
66 |
67 | $processes = [];
68 | // composer install
69 | $processes[] = $this->execute("{$recipe}.bash");
70 |
71 | // Composer Configuration
72 | $httpBasics = $this->projectConfiguration->get('composer.http_basic');
73 | if (\is_array($httpBasics)) {
74 | foreach ($httpBasics as $auth) {
75 | if (!isset($auth['host'], $auth['login'], $auth['password'])) {
76 | continue;
77 | }
78 | $processes[] = $this->globalExecute(
79 | '/usr/local/bin/composer config --global'.
80 | " http-basic.{$auth['host']} {$auth['login']} {$auth['password']}"
81 | );
82 | }
83 | }
84 |
85 | $tokens = $this->projectConfiguration->get('composer.token');
86 | if (\is_array($tokens)) {
87 | foreach ($tokens as $auth) {
88 | if (!isset($auth['host'], $auth['value'])) {
89 | continue;
90 | }
91 | $processes[] = $this->globalExecute(
92 | '/usr/local/bin/composer config --global'." github-oauth.{$auth['host']} {$auth['value']}"
93 | );
94 | }
95 | }
96 |
97 | return $processes;
98 | }
99 |
100 | public function eZInstall(string $version, string $repository, string $initialData): Process
101 | {
102 | $recipe = 'ez_install';
103 | $this->checkRecipeAvailability($recipe);
104 |
105 | return $this->execute("{$recipe}.bash {$repository} {$version} {$initialData}");
106 | }
107 |
108 | public function ibexaInstall(string $version, string $repository, string $initialData): Process
109 | {
110 | $recipe = 'ibexa_install';
111 | $this->checkRecipeAvailability($recipe);
112 |
113 | return $this->execute("{$recipe}.bash {$repository} {$version} {$initialData}");
114 | }
115 |
116 | public function eZInstallSolr(): Process
117 | {
118 | $recipe = 'ez_install_solr';
119 | $this->checkRecipeAvailability($recipe);
120 |
121 | return $this->execute(
122 | "{$recipe}.bash {$this->projectConfiguration->get('provisioning.folder_name')} COMPOSER_INSTALL"
123 | );
124 | }
125 |
126 | public function indexSolr(): Process
127 | {
128 | $recipe = 'ez_install_solr';
129 | $this->checkRecipeAvailability($recipe);
130 |
131 | return $this->execute(
132 | "{$recipe}.bash {$this->projectConfiguration->get('provisioning.folder_name')} INDEX"
133 | );
134 | }
135 |
136 | public function createCore(): Process
137 | {
138 | $recipe = 'ez_install_solr';
139 | $this->checkRecipeAvailability($recipe);
140 |
141 | $provisioningFolder = $this->projectConfiguration->get('provisioning.folder_name');
142 |
143 | return $this->execute(
144 | "{$recipe}.bash {$provisioningFolder} CREATE_CORE",
145 | 'solr',
146 | 'solr'
147 | );
148 | }
149 |
150 | public function eZCreate(): Process
151 | {
152 | $recipe = 'ez_create';
153 | $this->checkRecipeAvailability($recipe);
154 |
155 | return $this->execute("{$recipe}.bash");
156 | }
157 |
158 | public function dumpData(): Process
159 | {
160 | $recipe = 'create_dump';
161 | $this->checkRecipeAvailability($recipe);
162 |
163 | return $this->execute("{$recipe}.bash");
164 | }
165 |
166 | public function importData(): Process
167 | {
168 | $recipe = 'import_dump';
169 | $this->checkRecipeAvailability($recipe);
170 |
171 | return $this->execute("{$recipe}.bash");
172 | }
173 |
174 | public function runSymfomyCommand(string $arguments): Process
175 | {
176 | $consolePath = $this->dockerClient->isEzPlatform2x() ? 'bin/console' : 'app/console';
177 |
178 | return $this->execute("ezplatform/{$consolePath} {$arguments}");
179 | }
180 |
181 | public function runComposerCommand(string $arguments): Process
182 | {
183 | return $this->globalExecute(
184 | '/usr/local/bin/composer --working-dir='.$this->dockerClient->getProjectPathContainer().'/ezplatform '.
185 | $arguments
186 | );
187 | }
188 |
189 | protected function execute(string $command, string $user = 'www-data', string $service = 'engine')
190 | {
191 | $command = $this->dockerClient->getProjectPathContainer().'/'.$command;
192 |
193 | return $this->globalExecute($command, $user, $service);
194 | }
195 |
196 | protected function globalExecute(string $command, string $user = 'www-data', string $service = 'engine')
197 | {
198 | $args = ['--user', $user];
199 |
200 | foreach ($this->dockerEnvVars as $envVar) {
201 | $args = array_merge($args, ['--env', $envVar]);
202 | }
203 |
204 | return $this->dockerClient->exec($command, $args, $service);
205 | }
206 | }
207 |
--------------------------------------------------------------------------------
/src/DependencyInjection/CommandPass.php:
--------------------------------------------------------------------------------
1 | env = $env;
30 | }
31 |
32 | public function process(ContainerBuilder $container): void
33 | {
34 | if (\in_array($this->env, ['dev', 'test'])) {
35 | $definition = new Definition(Test::class);
36 | $definition->addTag('ezlaunchpad.command');
37 | $definition->setPublic(true);
38 | $container->setDefinition('ez.launchpad.test', $definition);
39 | $definition = new Definition(TestDockerClient::class);
40 | $definition->addTag('ezlaunchpad.command');
41 | $definition->setPublic(true);
42 | $container->setDefinition('ez.launchpad.testdockerclient', $definition);
43 | }
44 |
45 | $commands = $container->findTaggedServiceIds('ezlaunchpad.command');
46 | foreach ($commands as $id => $tags) {
47 | $commandDefinition = $container->getDefinition($id);
48 | $commandDefinition->addMethodCall('setProjectConfiguration', [new Reference(ProjectConfiguration::class)]);
49 | $commandDefinition->addMethodCall('setAppDir', [$container->getParameter('app_dir')]);
50 | $commandDefinition->addMethodCall('setProjectPath', [$container->getParameter('project_path')]);
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/Listener/ApplicationUpdate.php:
--------------------------------------------------------------------------------
1 | parameters = $parameters;
34 | $this->projectConfiguration = $configuration;
35 | }
36 |
37 | public function onCommandAction(ConsoleCommandEvent $event): void
38 | {
39 | $command = $event->getCommand();
40 |
41 | if (!$command instanceof BaseCommand || \in_array($command->getName(), ['self-update', 'rollback'])) {
42 | return;
43 | }
44 |
45 | $io = new SymfonyStyle($event->getInput(), $event->getOutput());
46 |
47 | $authorized = [
48 | 'list', 'help', 'test', 'docker:initialize:skeleton',
49 | 'docker:initialize_ibexa', 'docker:initialize', 'docker:create',
50 | 'self-update', 'rollback',
51 | ];
52 | if (!\in_array($command->getName(), $authorized)) {
53 | $fs = new Filesystem();
54 | $currentPwd = getcwd();
55 | $provisioningFolder = $this->projectConfiguration->get('provisioning.folder_name');
56 | $dockerComposeFileName = $this->projectConfiguration->get('docker.compose_filename');
57 | $dockerEnv = $event->getInput()->hasOption('env') ? $event->getInput()->getOption(
58 | 'env'
59 | ) : 'dev';
60 | $dockerComposeFileFolder = NovaCollection(
61 | [$currentPwd, $provisioningFolder, $dockerEnv]
62 | )->implode(
63 | '/'
64 | );
65 |
66 | if (!$fs->exists($dockerComposeFileFolder."/{$dockerComposeFileName}")) {
67 | $io->error('Your are not in a folder managed by eZ Launchpad.');
68 | $event->disableCommand();
69 | $event->stopPropagation();
70 |
71 | return;
72 | }
73 | }
74 |
75 | // do not check anything on Github Actions
76 | if (false !== getenv('GITHUB_ACTIONS')) {
77 | return;
78 | }
79 |
80 | // check last time check
81 | if (null != $this->projectConfiguration->get('last_update_check')) {
82 | $lastUpdate = Carbon::createFromTimestamp($this->projectConfiguration->get('last_update_check'));
83 | /** @var Carbon $lastUpdate */
84 | $now = Carbon::now();
85 | if ($now > $lastUpdate->subDays(3)) {
86 | return;
87 | }
88 | }
89 |
90 | $releaseUrl = $this->parameters['release_url'];
91 | $releases = githubFetch($releaseUrl);
92 | if (null === $releases) {
93 | $io->comment('Cannot find new releases, please try later.');
94 |
95 | return;
96 | }
97 | $release = $releases[0];
98 | $currentVersion = normalizeVersion($command->getApplication()->getVersion());
99 | $lastVersion = normalizeVersion($release->tag_name);
100 |
101 | if ($lastVersion > $currentVersion) {
102 | $io->note('A new version of eZ Launchpad is available, please run self-update.');
103 | sleep(2);
104 | }
105 |
106 | if (!\in_array($command->getName(), ['list', 'help'])) {
107 | $this->projectConfiguration->setLocal('last_update_check', time());
108 | }
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/src/Listener/CommandException.php:
--------------------------------------------------------------------------------
1 | getCommand();
23 | if (!$command instanceof Command) {
24 | return;
25 | }
26 |
27 | // Ensure that docker is running
28 | $nonDockerCommandCheckList = [
29 | 'docker:initialize:skeleton', 'docker:initialize',
30 | ];
31 | if (($command instanceof DockerCommand) || (\in_array($command->getName(), $nonDockerCommandCheckList))) {
32 | $output = $return = null;
33 | exec('docker system info > /dev/null 2>&1', $output, $return);
34 | if (0 !== $return) {
35 | $io = new SymfonyStyle($event->getInput(), $event->getOutput());
36 | $io->error('You need to start Docker before to run that command.');
37 | $event->disableCommand();
38 | $event->stopPropagation();
39 |
40 | return;
41 | }
42 | }
43 |
44 | $fs = new Filesystem();
45 | $command->getRequiredRecipes()->each(
46 | function ($recipe) use ($fs, $command) {
47 | $fs->copy(
48 | "{$command->getPayloadDir()}/recipes/{$recipe}.bash",
49 | "{$command->getProjectPath()}/{$recipe}.bash",
50 | true
51 | );
52 | $fs->chmod("{$command->getProjectPath()}/{$recipe}.bash", 0755);
53 | }
54 | );
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/Listener/CommandTerminate.php:
--------------------------------------------------------------------------------
1 | getCommand();
21 | if (!$command instanceof Command) {
22 | return;
23 | }
24 | $fs = new Filesystem();
25 | $command->getRequiredRecipes()->each(
26 | function ($recipe) use ($fs, $command) {
27 | $fs->remove("{$command->getProjectPath()}/{$recipe}.bash");
28 | }
29 | );
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Listener/OSXListener.php:
--------------------------------------------------------------------------------
1 | optimizers = $optimizers;
28 | }
29 |
30 | public function onCommandAction(ConsoleCommandEvent $event): void
31 | {
32 | if (!EZ_ON_OSX) {
33 | return;
34 | }
35 | $command = $event->getCommand();
36 | if (!$command instanceof Command) {
37 | return;
38 | }
39 |
40 | // don't bother for those command
41 | if (\in_array($command->getName(), ['self-update', 'rollback', 'list', 'help', 'test'])) {
42 | return;
43 | }
44 |
45 | $io = new SymfonyStyle($event->getInput(), $event->getOutput());
46 |
47 | try {
48 | $version = $this->getDockerVersion();
49 | foreach ($this->optimizers as $optimizer) {
50 | /** @var OptimizerInterface $optimizer */
51 | if (
52 | $optimizer->supports($version) &&
53 | !$optimizer->isEnabled() &&
54 | $optimizer->hasPermission($io)
55 | ) {
56 | $optimizer->optimize($io, $command);
57 | // only one allowed
58 | break;
59 | }
60 | }
61 | // one of them has been enable
62 | foreach ($this->optimizers as $optimizer) {
63 | /** @var OptimizerInterface $optimizer */
64 | if ($optimizer->supports($version) && $optimizer->isEnabled()) {
65 | $command->setOptimizer($optimizer);
66 | }
67 | }
68 | } catch (\Exception $e) {
69 | $io->error($e->getMessage());
70 | $event->disableCommand();
71 | $event->stopPropagation();
72 |
73 | return;
74 | }
75 | }
76 |
77 | protected function getDockerVersion(): int
78 | {
79 | $output = $return = null;
80 | exec('docker -v 2>/dev/null', $output, $return);
81 | if (0 !== $return) {
82 | throw new RuntimeException('You need to install Docker for Mac before to run that command.');
83 | }
84 | list($version, $build) = explode(',', $output[0]);
85 | unset($build);
86 | $result = preg_replace('/([^ ]*) ([^ ]*) ([0-9\\.]*)-?([a-zA-z]*)/ui', '$3', $version);
87 | list($major, $minor, $patch) = explode('.', $result);
88 | unset($patch);
89 | $normalizedVersion = (int) $major * 100 + $minor;
90 |
91 | return (int) $normalizedVersion;
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/bootstrap.php:
--------------------------------------------------------------------------------
1 | = 10) && ($minor >= 15)) || ($major >= 11);
55 | } else {
56 | $isCatalina = false;
57 | }
58 | }
59 |
60 | if (!$isCatalina) {
61 | return $path;
62 | }
63 |
64 | return str_replace('/Users', '/System/Volumes/Data/Users', $path);
65 | }
66 |
67 | function githubFetch(string $url, bool $toJson = true)
68 | {
69 | $context = stream_context_create(
70 | [
71 | 'http' => [
72 | 'method' => 'GET',
73 | 'header' => [
74 | 'User-Agent: eZ Launchpad Installer',
75 | ],
76 | ],
77 | ]
78 | );
79 |
80 | $content = @file_get_contents($url, false, $context);
81 |
82 | if (false === $content) {
83 | return null;
84 | }
85 |
86 | if (false === $toJson) {
87 | return $content;
88 | }
89 |
90 | return json_decode($content, false);
91 | }
92 |
93 | function normalizeVersion(string $versionName): int
94 | {
95 | if ('v' !== $versionName[0]) {
96 | return 0;
97 | }
98 | $version = substr($versionName, 1);
99 | $result = preg_replace('/([^ ]*) ([^ ]*) ([0-9.]*)-?([a-zA-z]*)/ui', '$3', $version);
100 | list($major, $minor, $patch) = explode('.', $result);
101 |
102 | return (int) $major * 10000 + (int) $minor * 100 + (int) $patch;
103 | }
104 |
--------------------------------------------------------------------------------
/tests/Tests/Behat/Commands/Context.php:
--------------------------------------------------------------------------------
1 | tester = new ApplicationTester(ApplicationFactory::create(false, 'test', "Linux"));
28 | }
29 |
30 | /**
31 | * @When /^I run "([^"]*)" command$/
32 | */
33 | public function iRunCommand($name, $params = []): void
34 | {
35 | $parameters = ['command' => $name];
36 |
37 | $parameters += $params;
38 | $this->tester->run($parameters);
39 | }
40 |
41 | /**
42 | * @Then /^I should see "([^"]*)"$/
43 | */
44 | public function iShouldSee($value): void
45 | {
46 | $matches = null;
47 | $output = $this->tester->getDisplay();
48 | if (preg_match('/(.*) OR (.*)/us', $value)) {
49 | preg_match_all('/(.*) OR (.*)/us', $value, $matches);
50 | if ((strpos($output, $matches[1][0]) === false) && (strpos($output, $matches[2][0]) === false)) {
51 | throw new Exception(
52 | sprintf('Did not see either "%s" OR "%s" in output "%s"', $matches[1][0], $matches[2][0], $output)
53 | );
54 | }
55 | } else {
56 | if (strpos($output, $value) === false) {
57 | throw new Exception(sprintf('Did not see "%s" in output "%s"', $value, $output));
58 | }
59 | }
60 | }
61 |
62 | /**
63 | * @When /^I run "([^"]*)" command with parameter "([^"]*)": "([^"]*)"$/
64 | */
65 | public function iRunCommandWithParameter($name, $paramName, $params): void
66 | {
67 | $this->iRunCommand($name, [$paramName => explode(' ', $params)]);
68 | }
69 |
70 | /**
71 | * @Then /^I should see:$/
72 | */
73 | public function iShouldSee1(TableNode $table): void
74 | {
75 | foreach ($table->getRows() as $value) {
76 | $this->iShouldSee($value[0]);
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/tests/Tests/Behat/Commands/features/test.feature:
--------------------------------------------------------------------------------
1 | Feature: Test command
2 |
3 | Scenario: Running test command
4 | When I run "test" command
5 | Then I should see "Test2"
6 | Then I should see:
7 | | Test1 |
8 | | Test3 |
9 |
10 |
--------------------------------------------------------------------------------
/tests/Tests/Command/Test.php:
--------------------------------------------------------------------------------
1 | setName('test')->setDescription('Test');
22 | $this->setHidden(true);
23 | }
24 |
25 | protected function execute(InputInterface $input, OutputInterface $output): int
26 | {
27 | $this->io->writeln('Test1');
28 | $this->io->writeln('Test2');
29 | $this->io->writeln('Test3');
30 |
31 | return Command::SUCCESS;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/tests/Tests/Command/TestDockerClient.php:
--------------------------------------------------------------------------------
1 | setName('testdockerclient')->setDescription('Test Docker Client');
22 | $this->setHidden(true);
23 | }
24 |
25 | protected function execute(InputInterface $input, OutputInterface $output): void
26 | {
27 | $this->io->writeln('Test1');
28 | $this->io->writeln('Test2');
29 | $this->io->writeln('Test3');
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/tests/Tests/Unit/BehatTest.php:
--------------------------------------------------------------------------------
1 | createApplication();
32 | $input = new ArrayInput(['--format' => ['progress'], '--config' => __DIR__.'/../../behat.yml']);
33 | $output = new ConsoleOutput();
34 | $bApplication->setAutoExit(false);
35 | $result = $bApplication->run($input, $output);
36 | $this->assertEquals(0, $result);
37 | } catch (Exception $exception) {
38 | $this->fail($exception->getMessage());
39 | }
40 |
41 | return true;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/tests/Tests/Unit/ConfigurationTest.php:
--------------------------------------------------------------------------------
1 | [
23 | "compose_filename" => "docker-compose.yml",
24 | "network_prefix_port" => "42",
25 | "host_machine_mapping" => null,
26 | "network_name" => "default-ezlaunchpad",
27 | "host_composer_cache_dir" => null
28 | ],
29 | "provisioning" => [
30 | "folder_name" => "provisioning"
31 | ],
32 | "last_update_check" => null
33 | ];
34 |
35 | protected function process($configs): array
36 | {
37 | $processor = new Processor();
38 | $configuration = new Configuration();
39 |
40 | return $processor->processConfiguration(
41 | $configuration,
42 | $configs
43 | );
44 | }
45 |
46 | public function testDefaultLoad(): void
47 | {
48 | $config = $this->process([]);
49 | $this->assertEquals(static::$defaultConfiguration, $config);
50 | }
51 |
52 | public function getYamlExamples(): array
53 | {
54 | return [
55 | ['', 'ok'],
56 | [
57 | '
58 | last_update_check: 1491955697
59 | provisioning:
60 | folder_name: provisio
61 | docker:
62 | compose_filename: compose.yml
63 | network_name: something
64 | network_prefix_port: 43
65 | ', 'ok',
66 | ],
67 | [
68 | '
69 | provisioning:
70 | docker:
71 | ', 'default',
72 | ],
73 | [
74 | '
75 | docker:
76 | ', 'default',
77 | ],
78 | [
79 | '
80 | last_update_check: ~
81 | ', 'default',
82 | ],
83 | [
84 | '
85 | provisioni2ng:
86 | ', 'exception',
87 | ],
88 | ];
89 | }
90 |
91 | /**
92 | * @dataProvider getYamlExamples
93 | */
94 | public function testYamlLoading($yaml, $expected): void
95 | {
96 | if ($expected === 'exception') {
97 | $this->expectException(Exception::class);
98 | }
99 |
100 | $configuration = Yaml::parse($yaml);
101 | $config = $this->process([$configuration]);
102 |
103 | if ($expected === 'ok') {
104 | $this->assertIsArray($config);
105 | }
106 | if ($expected === 'default') {
107 | $this->assertIsArray($config);
108 | $this->assertEquals(static::$defaultConfiguration, $config);
109 | }
110 | }
111 |
112 | /**
113 | * @dataProvider getYamlExamples
114 | */
115 | public function testYamlException($yaml, $expected)
116 | {
117 | $this->expectException(InvalidConfigurationException::class);
118 | $configuration = Yaml::parse($yaml);
119 | $this->process([$configuration]);
120 | if ($expected !== 'exception') {
121 | throw new InvalidConfigurationException('mock');
122 | }
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/tests/Tests/Unit/DockerClientTest.php:
--------------------------------------------------------------------------------
1 | environmentVariables = $this->getDockerClientEnvironmentVariables();
26 | }
27 |
28 | public function testEnvVariables(): void
29 | {
30 | $this->assertEquals($this->environmentVariables, $this->getDockerClient()->getComposeEnvVariables());
31 | }
32 |
33 | public function testGetCommand(): void
34 | {
35 | $vars = NovaCollection($this->environmentVariables);
36 |
37 | $prefix = $vars->map(
38 | function ($value, $key) {
39 | return $key.'='.$value;
40 | }
41 | )->implode(' ');
42 |
43 | $expected = "{$prefix} docker-compose -p test -f ".$this->getDockerComposeFilePath();
44 | $this->assertEquals($expected, $this->getDockerClient()->getComposeCommand());
45 | }
46 |
47 | public function getTestedActions(): array
48 | {
49 | return [
50 | ['ps', [[]], 'ps'],
51 | ['ps', [['-q']], 'ps -q'],
52 | ['ps', [['-q', '-ez']], 'ps -q -ez'],
53 | ['down', [[]], 'down'],
54 | ['down', [['-q']], 'down -q'],
55 | ['down', [['-q', '-ez']], 'down -q -ez'],
56 | ['start', ['plop'], 'start plop'],
57 | ['stop', ['plop'], 'stop plop'],
58 | ['restart', ['plop'], 'restart plop'],
59 |
60 | ['logs', [['-q', '-ez'], 'plop'], 'logs -q -ez plop'],
61 | ['up', [['-q', '-ez'], 'plop'], 'up -q -ez plop'],
62 | ['build', [['-q', '-ez'], 'plop'], 'build -q -ez plop'],
63 | ['remove', [['-q', '-ez'], 'plop'], 'rm -q -ez plop'],
64 |
65 | ['exec', ['/bin/bash', ['-q', '-ez'], 'plop'], 'exec -q -ez plop /bin/bash'],
66 | ['exec', ['/bin/bash', [], 'plop'], 'exec plop /bin/bash'],
67 |
68 | // no tty
69 | ['exec', ['/bin/bash', ['-q', '-ez'], 'plop'], 'exec -T -q -ez plop /bin/bash', false],
70 | ['exec', ['/bin/bash', [], 'plop'], 'exec -T plop /bin/bash', false],
71 | ];
72 | }
73 |
74 | /**
75 | * @dataProvider getTestedActions
76 | */
77 | public function testRun(string $method, array $args, string $expectedCommandSuffix, bool $hasTty = true): void
78 | {
79 | $client = $this->getDockerClient($hasTty);
80 | $mockedResults = \call_user_func_array([$client, $method], $args);
81 |
82 | $this->assertCount(2, $mockedResults);
83 | $this->assertEquals($mockedResults[1], $this->environmentVariables);
84 |
85 | $command = "docker-compose -p test -f ".$this->getDockerComposeFilePath();
86 | $suffix = trim(str_replace($command, '', $mockedResults[0]));
87 |
88 | $this->assertEquals($expectedCommandSuffix, $suffix);
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/tests/Tests/Unit/DockerComposeTest.php:
--------------------------------------------------------------------------------
1 | compose = new DockerCompose(__DIR__."/../../../payload/dev/docker-compose.yml");
28 | }
29 |
30 | public function testFiltering(): void
31 | {
32 | $this->compose->filterServices(['engine', 'db']);
33 | $this->assertCount(2, $this->compose->getServices());
34 | }
35 |
36 | public function testCleanupVolumesInitialize(): void
37 | {
38 | $this->compose->cleanForInitialize();
39 | foreach ($this->compose->getServices() as $service) {
40 | if (!isset($service['volumes'])) {
41 | continue;
42 | }
43 | foreach ($service['volumes'] as $volumes) {
44 | $this->assertNotRegExp(
45 | "/ezplatform/",
46 | $volumes,
47 | 'It should not be any ezplatform mount for initialize.'
48 | );
49 | }
50 | }
51 | }
52 |
53 | public function testCleanupEnvsInitialize(): void
54 | {
55 | $this->compose->cleanForInitialize();
56 | foreach ($this->compose->getServices() as $name => $service) {
57 | if (!isset($service['environment'])) {
58 | continue;
59 | }
60 | foreach ($service['environment'] as $env) {
61 | $this->assertNotRegExp(
62 | "/(CUSTOM_CACHE_POOL|CACHE_HOST|CACHE_REDIS_PORT|SEARCH_ENGINE|SOLR_DSN)/",
63 | $env
64 | );
65 | }
66 | }
67 | }
68 |
69 | public function getCleanEnvVarsData(): array
70 | {
71 | return [
72 | [
73 | ['engine', 'redis'],
74 | ['SEARCH_ENGINE', 'SOLR_DSN']
75 | ],
76 | [
77 | ['engine', 'solr'],
78 | ['CACHE_HOST', 'CACHE_REDIS_PORT', 'CACHE_REDIS_PORT']
79 | ],
80 | [
81 | ['engine'],
82 | ['CACHE_HOST', 'CACHE_REDIS_PORT', 'CACHE_REDIS_PORT', 'SEARCH_ENGINE', 'SOLR_DSN']
83 | ]
84 | ];
85 | }
86 |
87 | /**
88 | * @dataProvider getCleanEnvVarsData
89 | */
90 | public function testCleanEnvVars($services, $toCheckVars): void
91 | {
92 | $this->compose->filterServices($services);
93 | $this->compose->removeUselessEnvironmentsVariables();
94 |
95 | $environments = $this->compose->getServices()['engine']['environment'];
96 | $vars = [];
97 |
98 | foreach ($environments as $env) {
99 | if (!strpos($env, '=')) {
100 | continue;
101 | }
102 | list($key, $values) = explode("=", $env);
103 |
104 | $vars[] = $key;
105 | }
106 | foreach ($toCheckVars as $var) {
107 | $this->assertNotContains($var, $vars);
108 | }
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/tests/Tests/Unit/ProjectConfigurationTest.php:
--------------------------------------------------------------------------------
1 | getConfiguration();
45 | $this->assertEquals($projectConfiguration->get($key), $expectedValue);
46 | }
47 |
48 | public function testSet($where = 'local')
49 | {
50 | $method = "set".ucfirst($where);
51 | $var = 'docker.compose_filename';
52 | $firstProjectConfiguration = $this->getConfiguration();
53 | $this->assertEquals($firstProjectConfiguration->get($var), 'docker-compose-test.yml');
54 | $firstProjectConfiguration->$method($var, 'docker-compose-test.yml_CHANGED');
55 | $this->assertEquals($firstProjectConfiguration->get($var), 'docker-compose-test.yml_CHANGED');
56 | $secondProjectConfiguration = $this->getConfiguration();
57 | $this->assertEquals($secondProjectConfiguration->get($var), 'docker-compose-test.yml_CHANGED');
58 | $this->assertEquals($firstProjectConfiguration, $secondProjectConfiguration);
59 | }
60 |
61 | public function testSetGlobal(): void
62 | {
63 | $this->testSet('global');
64 |
65 | $configuration = $this->getConfiguration();
66 | $configuration->setGlobal('provisioning.folder_name', 'untruc');
67 | // change on the fly
68 | $this->assertEquals($configuration->get('provisioning.folder_name'), 'untruc');
69 |
70 | // does not the next load
71 | $secondProjectConfiguration = $this->getConfiguration();
72 | $this->assertEquals($secondProjectConfiguration->get('provisioning.folder_name'), 'provisioning_test');
73 | }
74 |
75 | public function testDockerComposerGet(): void
76 | {
77 | $configuration = $this->getConfiguration();
78 | $dockerCompose = $configuration->getDockerCompose();
79 | $this->assertInstanceOf(DockerCompose::class, $dockerCompose);
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/tests/Tests/Unit/RequiredFilesTest.php:
--------------------------------------------------------------------------------
1 | directories as $directory) {
24 | $data[] = [$directory, static::DIRECTORY];
25 | }
26 | foreach ($box->files as $directory) {
27 | $data[] = [$directory, static::FILE];
28 | }
29 |
30 | $data[] = [$box->main, static::FILE];
31 |
32 | return $data;
33 | }
34 |
35 | public function testBoxJsonExist(): void
36 | {
37 | $this->assertFileExists($appDir = __DIR__."/../../../box.json");
38 | }
39 |
40 | /**
41 | * @dataProvider getRequiredFiles
42 | */
43 | public function testBoxFileIsPresent($file, $type): void
44 | {
45 | $appDir = __DIR__."/../../..";
46 | $this->$type("{$appDir}/{$file}");
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/tests/Tests/Unit/TaskExecutorTest.php:
--------------------------------------------------------------------------------
1 | files()->in(__DIR__."/../../../payload/recipes")->name("*.bash");
31 |
32 | $recipes = NovaCollection([]);
33 | foreach ($files as $file) {
34 | /** @var SplFileInfo $file */
35 | $recipes->add(str_replace(".bash", "", $file->getFilename()));
36 | }
37 | $this->executor = new TaskExecutor($this->getDockerClient(), $this->getConfiguration(), $recipes);
38 | }
39 |
40 | /**
41 | *
42 | */
43 | public function testComposerInstall(): void
44 | {
45 | $command = "docker-compose -p test -f ".$this->getDockerComposeFilePath();
46 | $results = $this->executor->composerInstall();
47 | $this->assertCount(3, $results);
48 |
49 | $suffixes = [];
50 | foreach ($results as $result) {
51 | $suffixes[] = trim(str_replace($command, '', $result[0]));
52 | }
53 |
54 | $startWith = "exec --user www-data engine";
55 | $path = $this->getDockerClient()->getProjectPathContainer();
56 |
57 | $this->assertEquals("{$startWith} {$path}/composer_install.bash", $suffixes[0]);
58 | $this->assertEquals(
59 | "{$startWith} /usr/local/bin/composer config --global http-basic.ez.no login novactive",
60 | $suffixes[1]
61 | );
62 | $this->assertEquals(
63 | "{$startWith} /usr/local/bin/composer config --global http-basic.plopix.net login pass",
64 | $suffixes[2]
65 | );
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/tests/Tests/Unit/TestCase.php:
--------------------------------------------------------------------------------
1 | root = vfsStream::setup('ezlaunchpad');
32 | $globalConfiguration = vfsStream::url("ezlaunchpad/ez.yml");
33 | $localConfiguration = vfsStream::url("ezlaunchpad/.ezlaunchpad.yml");
34 |
35 | file_put_contents(
36 | $globalConfiguration,
37 | '
38 | docker:
39 | host_machine_mapping: "/Users/plopix/DOCKFILES:/data/DOCKER_SOURCES"
40 | host_composer_cache_dir: "/data/DOCKER_SOURCES/.composer_cache"
41 | compose_filename: docker-compose-test.yml
42 |
43 | provisioning:
44 | folder_name: "provisioning2ouf"
45 |
46 | composer:
47 | http_basic:
48 | ez:
49 | host: ez.no
50 | login: login
51 | password: novactive
52 | plopix:
53 | host: plopix.net
54 | login: login
55 | password: pass
56 | '
57 | );
58 |
59 | file_put_contents(
60 | $localConfiguration,
61 | '
62 | last_update_check: 1491955697
63 | provisioning:
64 | folder_name: provisioning_test
65 | docker:
66 | network_name: newversion_test
67 | network_prefix_port: 123
68 | '
69 | );
70 | }
71 |
72 | protected function process($configs): array
73 | {
74 | $processor = new Processor();
75 | $configuration = new Configuration();
76 |
77 | return $processor->processConfiguration(
78 | $configuration,
79 | $configs
80 | );
81 | }
82 |
83 | protected function getConfiguration(): ProjectConfiguration
84 | {
85 | $globalFile = $this->root->getChild('ez.yml')->url();
86 | $localFile = $this->root->getChild('.ezlaunchpad.yml')->url();
87 |
88 | $pConfiguration = new ProjectConfiguration(
89 | $globalFile,
90 | $localFile,
91 | $this->process(
92 | [
93 | Yaml::parse(file_get_contents($globalFile)),
94 | Yaml::parse(file_get_contents($localFile)),
95 | ]
96 | )
97 | );
98 | $pConfiguration->setEnvironment('dev');
99 |
100 | return $pConfiguration;
101 | }
102 |
103 | public function getDockerComposeFilePath(): string
104 | {
105 | return __DIR__."/../../../payload/dev/docker-compose.yml";
106 | }
107 |
108 | public function getDockerClient(bool $hasTty = true): Docker
109 | {
110 | $options = [
111 | 'compose-file' => $this->getDockerComposeFilePath(),
112 | 'network-name' => "test",
113 | 'network-prefix-port' => 42,
114 | 'project-path' => getcwd(),
115 | 'provisioning-folder-name' => 'provisioning',
116 | ];
117 |
118 | $processRunnerMock = $this->getMockBuilder(ProcessRunner::class)->getMock();
119 |
120 | $processRunnerMock
121 | ->method('run')
122 | ->will(
123 | $this->returnCallback(
124 | function () {
125 | return \func_get_args();
126 | }
127 | )
128 | );
129 |
130 | $processRunnerMock
131 | ->method('hasTty')
132 | ->willReturn($hasTty);
133 |
134 | return new Docker($options, $processRunnerMock);
135 | }
136 |
137 | public function getDockerClientEnvironmentVariables(): array
138 | {
139 | return [
140 | 'PROJECTNETWORKNAME' => 'test',
141 | "PROJECTPORTPREFIX" => 42,
142 | "PROJECTCOMPOSEPATH" => "../../",
143 | "PROVISIONINGFOLDERNAME" => "provisioning",
144 | "HOST_COMPOSER_CACHE_DIR" => MacOSPatherize(getenv('HOME')."/.composer/cache"),
145 | "DEV_UID" => getmyuid(),
146 | "DEV_GID" => getmygid(),
147 | 'COMPOSER_CACHE_DIR' => "/var/www/composer_cache",
148 | 'PROJECTMAPPINGFOLDER' => "/var/www/html/project",
149 | 'BLACKFIRE_CLIENT_ID' => getenv('BLACKFIRE_CLIENT_ID'),
150 | 'BLACKFIRE_CLIENT_TOKEN' => getenv('BLACKFIRE_CLIENT_TOKEN'),
151 | 'BLACKFIRE_SERVER_ID' => getenv('BLACKFIRE_SERVER_ID'),
152 | 'BLACKFIRE_SERVER_TOKEN' => getenv('BLACKFIRE_SERVER_TOKEN'),
153 | 'DOCKER_HOST' => getenv('DOCKER_HOST'),
154 | 'DOCKER_CERT_PATH' => getenv('DOCKER_CERT_PATH'),
155 | 'DOCKER_TLS_VERIFY' => getenv('DOCKER_TLS_VERIFY'),
156 | 'PATH' => getenv('PATH'),
157 | 'XDEBUG_ENABLED' => getenv('XDEBUG_ENABLED') === false ? '0' : '1'
158 | ];
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/tests/behat.yml:
--------------------------------------------------------------------------------
1 | default:
2 | calls:
3 | #php -r "echo E_ALL & ~E_USER_DEPRECATED;"
4 | error_reporting: 16383
5 | suites:
6 | commands:
7 | paths:
8 | - Tests/Behat/Commands
9 | contexts:
10 | - eZ\Launchpad\Tests\Behat\Commands\Context
11 |
--------------------------------------------------------------------------------
/tests/bootstrap.php:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 | ./Tests/Unit
21 |
22 |
23 |
24 |
25 | ../src/
26 |
27 | ../src/bootstrap.php
28 | ../src/functions.php
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/tests/postman/collection-1x.json:
--------------------------------------------------------------------------------
1 | {
2 | "variables": [],
3 | "info": {
4 | "name": "eZ Launchpad",
5 | "_postman_id": "8c9b1b7c-3cab-0d63-5514-e4712892b3de",
6 | "description": "A Collection to test that eZ Launchpad initialize correctly",
7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json"
8 | },
9 | "item": [
10 | {
11 | "name": "Load Home Page",
12 | "event": [
13 | {
14 | "listen": "test",
15 | "script": {
16 | "type": "text/javascript",
17 | "exec": [
18 | "tests[\"Page loaded\"] = responseBody.has(\"eZ Platform\");",
19 | "tests[\"Status code is 200\"] = responseCode.code === 200;"
20 | ]
21 | }
22 | }
23 | ],
24 | "request": {
25 | "url": "http://localhost:42080/",
26 | "method": "GET",
27 | "header": [],
28 | "body": {},
29 | "description": ""
30 | },
31 | "response": []
32 | },
33 | {
34 | "name": "Load Admin Page",
35 | "event": [
36 | {
37 | "listen": "test",
38 | "script": {
39 | "type": "text/javascript",
40 | "exec": [
41 | "tests[\"Page loaded\"] = responseBody.has(\"eZ Platform UI\");",
42 | "tests[\"Page loaded 2\"] = responseBody.has(\"Loading the application...\");",
43 | "tests[\"Status code is 200\"] = responseCode.code === 200;"
44 | ]
45 | }
46 | }
47 | ],
48 | "request": {
49 | "url": "http://localhost:42080/ez",
50 | "method": "GET",
51 | "header": [],
52 | "body": {},
53 | "description": ""
54 | },
55 | "response": []
56 | },
57 | {
58 | "name": "Front Login Failure - DB Test",
59 | "event": [
60 | {
61 | "listen": "test",
62 | "script": {
63 | "type": "text/javascript",
64 | "exec": [
65 | "tests[\"Login Failed\"] = responseBody.has(\"Bad credentials\");",
66 | "tests[\"Status code is 200\"] = responseCode.code === 200;"
67 | ]
68 | }
69 | }
70 | ],
71 | "request": {
72 | "url": "http://localhost:42080/login_check",
73 | "method": "POST",
74 | "header": [],
75 | "body": {
76 | "mode": "formdata",
77 | "formdata": [
78 | {
79 | "key": "_username",
80 | "value": "Plopix",
81 | "description": "",
82 | "type": "text"
83 | },
84 | {
85 | "key": "_password",
86 | "value": "Novactive",
87 | "description": "",
88 | "type": "text"
89 | }
90 | ]
91 | },
92 | "description": ""
93 | },
94 | "response": []
95 | },
96 | {
97 | "name": "Front Login OK - DB Test",
98 | "event": [
99 | {
100 | "listen": "test",
101 | "script": {
102 | "type": "text/javascript",
103 | "exec": [
104 | "tests[\"Login success\"] = !responseBody.has(\"Bad credentials\");",
105 | "tests[\"Status code is 200\"] = responseCode.code === 200;"
106 | ]
107 | }
108 | }
109 | ],
110 | "request": {
111 | "url": "http://localhost:42080/login_check",
112 | "method": "POST",
113 | "header": [],
114 | "body": {
115 | "mode": "formdata",
116 | "formdata": [
117 | {
118 | "key": "_username",
119 | "value": "admin",
120 | "description": "",
121 | "type": "text"
122 | },
123 | {
124 | "key": "_password",
125 | "value": "publish",
126 | "description": "",
127 | "type": "text"
128 | }
129 | ]
130 | },
131 | "description": ""
132 | },
133 | "response": []
134 | }
135 | ]
136 | }
137 |
--------------------------------------------------------------------------------
/tests/postman/collection-2x.json:
--------------------------------------------------------------------------------
1 | {
2 | "info": {
3 | "name": "eZ Launchpad",
4 | "_postman_id": "8c9b1b7c-3cab-0d63-5514-e4712892b3de",
5 | "description": "A Collection to test that eZ Launchpad initialize correctly",
6 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
7 | },
8 | "item": [
9 | {
10 | "name": "Load Home Page",
11 | "event": [
12 | {
13 | "listen": "test",
14 | "script": {
15 | "type": "text/javascript",
16 | "exec": [
17 | "tests[\"Status code is 200\"] = responseCode.code === 200;"
18 | ]
19 | }
20 | }
21 | ],
22 | "request": {
23 | "method": "GET",
24 | "header": [],
25 | "body": {},
26 | "url": {
27 | "raw": "http://localhost:42080/",
28 | "protocol": "http",
29 | "host": [
30 | "localhost"
31 | ],
32 | "port": "42080",
33 | "path": [
34 | ""
35 | ]
36 | },
37 | "description": ""
38 | },
39 | "response": []
40 | },
41 | {
42 | "name": "Load Admin Page",
43 | "event": [
44 | {
45 | "listen": "test",
46 | "script": {
47 | "id": "19d338c4-e169-49b3-a383-766756df60ce",
48 | "type": "text/javascript",
49 | "exec": [
50 | "tests[\"Status code is 200\"] = responseCode.code === 200;"
51 | ]
52 | }
53 | }
54 | ],
55 | "request": {
56 | "method": "GET",
57 | "header": [],
58 | "body": {},
59 | "url": {
60 | "raw": "http://localhost:42080/admin/login",
61 | "protocol": "http",
62 | "host": [
63 | "localhost"
64 | ],
65 | "port": "42080",
66 | "path": [
67 | "admin",
68 | "login"
69 | ]
70 | },
71 | "description": ""
72 | },
73 | "response": []
74 | }
75 | ]
76 | }
77 |
--------------------------------------------------------------------------------