mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-23 09:53:15 +00:00
Merge pull request #3401 from alchemy-fr/PHRAS-2981-builder-for-dev
PHRAS-2981 #comment merge add dev utils to builder image
This commit is contained in:
@@ -23,7 +23,7 @@
|
||||
/datas
|
||||
/docker-compose.*
|
||||
/logs
|
||||
/nodes_modules
|
||||
/node_modules
|
||||
/plugins
|
||||
/tmp
|
||||
/vendor
|
||||
|
8
.env
8
.env
@@ -1,3 +1,4 @@
|
||||
PHRASEANET_PROJECT_NAME=Phraseanet
|
||||
# Registry from where you pull Docker images
|
||||
PHRASEANET_DOCKER_REGISTRY=local
|
||||
# Tag of the Docker images
|
||||
@@ -70,3 +71,10 @@ PHRASEANET_DB_DIR=./volumes/db
|
||||
PHRASEANET_ELASTICSEARCH_DIR=./volumes/elasticsearch
|
||||
PHRASEANET_THUMBNAILS_DIR=./www/thumbnails
|
||||
PHRASEANET_TMP_DIR=./tmp
|
||||
|
||||
# For dev who don't have SSH_AUTH_SOCK (avoid an empty volume name)
|
||||
SSH_AUTH_SOCK=/dev/null
|
||||
|
||||
# Plugin support
|
||||
PHRASEANET_PLUGINS=
|
||||
PHRASEANET_SSH_PRIVATE_KEY=
|
||||
|
35
Dockerfile
35
Dockerfile
@@ -82,8 +82,19 @@ RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
nodejs \
|
||||
yarn \
|
||||
nano \
|
||||
vim \
|
||||
iputils-ping \
|
||||
zsh \
|
||||
ssh \
|
||||
telnet \
|
||||
autoconf \
|
||||
libtool \
|
||||
python \
|
||||
pkg-config \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists \
|
||||
&& git clone https://github.com/robbyrussell/oh-my-zsh.git /bootstrap/.oh-my-zsh \
|
||||
&& mkdir -p /var/alchemy/Phraseanet \
|
||||
&& chown -R app:app /var/alchemy
|
||||
|
||||
@@ -99,10 +110,28 @@ RUN composer install --prefer-dist --no-dev --no-progress --no-suggest --classma
|
||||
|
||||
COPY --chown=app . .
|
||||
|
||||
RUN rm -rf docker/phraseanet/root \
|
||||
&& make install
|
||||
RUN make install
|
||||
|
||||
ADD docker/phraseanet/ /
|
||||
ADD ./docker/builder/root /
|
||||
|
||||
# SSH Private repo
|
||||
ARG SSH_PRIVATE_KEY
|
||||
ARG PHRASEANET_PLUGINS
|
||||
|
||||
RUN ( \
|
||||
test ! -z "${SSH_PRIVATE_KEY}" \
|
||||
&& mkdir -p ~/.ssh \
|
||||
&& echo "${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa \
|
||||
# make sure github domain.com is accepted
|
||||
&& ssh-keyscan -H github.com >> ~/.ssh/known_hosts \
|
||||
&& chmod 600 ~/.ssh/id_rsa \
|
||||
) || echo "Skip SSH key"
|
||||
|
||||
RUN ./docker/phraseanet/plugins/console install
|
||||
|
||||
ENTRYPOINT ["/bootstrap/entrypoint.sh"]
|
||||
|
||||
CMD []
|
||||
|
||||
#########################################################################
|
||||
# Phraseanet web application image
|
||||
|
47
README.md
47
README.md
@@ -56,10 +56,17 @@ export PHRASEANET_APP_PORT=8082
|
||||
|
||||
It may be easier to deal with a local file to manage our env variables.
|
||||
|
||||
You can add your `env.local` at the root of this project and define a command alias in your `~/.bashrc`:
|
||||
You can add your `env.local` at the root of this project and define a command function in your `~/.bashrc`:
|
||||
|
||||
```bash
|
||||
alias dc="env $(cat env.local | grep -v '#' | tr '\n' ' ') docker-compose"
|
||||
# ~/.bashrc or ~/.zshrc
|
||||
function dc() {
|
||||
if [ -f env.local ]; then
|
||||
env $(cat env.local | grep -v '#' | tr '\n' ' ') docker-compose $@
|
||||
else
|
||||
docker-compose $@
|
||||
fi
|
||||
}
|
||||
```
|
||||
|
||||
### Running the application
|
||||
@@ -105,6 +112,20 @@ This can be made easily from the builder container:
|
||||
> Please note that the phraseanet image does not contain nor `composer` neither `node` tools. This allow the final image to be slim.
|
||||
> If you need to use dev tools, ensure you are running the `builder` image!
|
||||
|
||||
### Developer shell
|
||||
|
||||
You can also obtain a shell access in builder container:
|
||||
|
||||
```bash
|
||||
docker-compose run --rm builder /bin/bash
|
||||
# or
|
||||
docker-compose run --rm builder /bin/zsh
|
||||
```
|
||||
|
||||
In this container you will have the same libraries (PHP, Node, composer, ...) that are used to build images.
|
||||
Also you have utils for development like telnet, ping, ssh, git, ...
|
||||
Your $HOME/.ssh directory is also mounted to builder's home with your ssh agent.
|
||||
|
||||
### Using Xdebug
|
||||
|
||||
Xdebug is enabled by default with the `docker-compose.override.yml`
|
||||
@@ -132,6 +153,28 @@ XDEBUG_REMOTE_HOST=host.docker.internal
|
||||
|
||||
> Don't forget to recreate your container (`docker-compose up -d phraseanet`)
|
||||
|
||||
### Build images with plugins
|
||||
|
||||
Plugins can be installed during build if you set the `PHRASEANET_PLUGINS` env var as follows:
|
||||
|
||||
```bash
|
||||
PHRASEANET_PLUGINS="git@github.com:alchemy-fr/Phraseanet-plugin-webgallery.git"
|
||||
|
||||
# You can optionally precise the branch to install
|
||||
# If not precised, the main branch will be pulled
|
||||
PHRASEANET_PLUGINS="git@github.com:alchemy-fr/Phraseanet-plugin-webgallery.git(custom-branch)"
|
||||
|
||||
# Plugins are separated by spaces
|
||||
PHRASEANET_PLUGINS="git@github.com:foo/bar.git(branch-1) git@github.com:baz/42.git"
|
||||
```
|
||||
|
||||
If you install private plugins, make sure you export your SSH private key content in order to allow docker build to access the GIT repository:
|
||||
```bash
|
||||
export PHRASEANET_SSH_PRIVATE_KEY=$(cat ~/.ssh/id_rsa)
|
||||
# or if your private key is protected by a passphrase:
|
||||
export PHRASEANET_SSH_PRIVATE_KEY=$(openssl rsa -in ~/.ssh/id_rsa -out /tmp/id_rsa_raw && cat /tmp/id_rsa_raw && rm /tmp/id_rsa_raw)
|
||||
```
|
||||
|
||||
# With Vagrant (deprecated)
|
||||
|
||||
## Development :
|
||||
|
@@ -10,25 +10,34 @@ services:
|
||||
|
||||
gateway:
|
||||
volumes:
|
||||
- ../:/var/alchemy
|
||||
- .:/var/alchemy/Phraseanet
|
||||
- ./docker/nginx/root/entrypoint.sh:/entrypoint.sh
|
||||
- ${PHRASEANET_DATA_DIR}:/var/alchemy/Phraseanet/datas:rw
|
||||
- ${PHRASEANET_THUMBNAILS_DIR}:/var/alchemy/Phraseanet/www/thumbnails:rw
|
||||
- ${PHRASEANET_TMP_DIR}:/var/alchemy/Phraseanet/tmp:rw
|
||||
|
||||
|
||||
|
||||
builder:
|
||||
build:
|
||||
context: .
|
||||
target: builder
|
||||
command: exit 0
|
||||
args:
|
||||
- SSH_PRIVATE_KEY=${PHRASEANET_SSH_PRIVATE_KEY}
|
||||
- PHRASEANET_PLUGINS=${PHRASEANET_PLUGINS}
|
||||
stdin_open: true
|
||||
tty: true
|
||||
volumes:
|
||||
- ../:/var/alchemy
|
||||
- .:/var/alchemy/Phraseanet
|
||||
- ${PHRASEANET_CONFIG_DIR}:/var/alchemy/Phraseanet/config:rw
|
||||
- ${PHRASEANET_LOGS_DIR}:/var/alchemy/Phraseanet/logs:rw
|
||||
- ${PHRASEANET_DATA_DIR}:/var/alchemy/Phraseanet/datas:rw
|
||||
- ${PHRASEANET_THUMBNAILS_DIR}:/var/alchemy/Phraseanet/www/thumbnails:rw
|
||||
- ${SSH_AUTH_SOCK}:/ssh-auth-sock
|
||||
- ${HOME}/.ssh:/home/app/.ssh
|
||||
- dev_vol:/home/app
|
||||
environment:
|
||||
- PHRASEANET_PROJECT_NAME
|
||||
|
||||
phraseanet:
|
||||
environment:
|
||||
@@ -36,6 +45,7 @@ services:
|
||||
- XDEBUG_CONFIG=remote_host=${XDEBUG_REMOTE_HOST} idekey=${IDE_KEY} remote_enable=1 profiler_enable=${XDEBUG_PROFILER_ENABLED} profiler_output_dir=/var/alchemy/Phraseanet/cache/profiler
|
||||
- PHP_IDE_CONFIG
|
||||
volumes:
|
||||
- ../:/var/alchemy
|
||||
- .:/var/alchemy/Phraseanet
|
||||
- ${PHRASEANET_CONFIG_DIR}:/var/alchemy/Phraseanet/config:rw
|
||||
- ${PHRASEANET_LOGS_DIR}:/var/alchemy/Phraseanet/logs:rw
|
||||
@@ -45,6 +55,7 @@ services:
|
||||
|
||||
worker:
|
||||
volumes:
|
||||
- ../:/var/alchemy
|
||||
- .:/var/alchemy/Phraseanet
|
||||
- ${PHRASEANET_CONFIG_DIR}:/var/alchemy/Phraseanet/config:rw
|
||||
- ${PHRASEANET_LOGS_DIR}:/var/alchemy/Phraseanet/logs:rw
|
||||
@@ -72,8 +83,17 @@ services:
|
||||
volumes:
|
||||
- ${PHRASEANET_ELASTICSEARCH_DIR}:/usr/share/elasticsearch/data:rw
|
||||
|
||||
kibana:
|
||||
image: kibana:4.6.6
|
||||
ports:
|
||||
- 5601:5601
|
||||
|
||||
networks:
|
||||
default:
|
||||
ipam:
|
||||
config:
|
||||
- subnet: $PHRASEANET_SUBNET_IPS
|
||||
|
||||
volumes:
|
||||
dev_vol:
|
||||
driver: local
|
||||
|
@@ -5,6 +5,9 @@ services:
|
||||
build:
|
||||
context: .
|
||||
target: phraseanet-nginx
|
||||
args:
|
||||
- SSH_PRIVATE_KEY=${PHRASEANET_SSH_PRIVATE_KEY}
|
||||
- PHRASEANET_PLUGINS=${PHRASEANET_PLUGINS}
|
||||
image: $PHRASEANET_DOCKER_REGISTRY/phraseanet-nginx:$PHRASEANET_DOCKER_TAG
|
||||
restart: on-failure
|
||||
volumes:
|
||||
@@ -21,6 +24,9 @@ services:
|
||||
build:
|
||||
context: .
|
||||
target: phraseanet-fpm
|
||||
args:
|
||||
- SSH_PRIVATE_KEY=${PHRASEANET_SSH_PRIVATE_KEY}
|
||||
- PHRASEANET_PLUGINS=${PHRASEANET_PLUGINS}
|
||||
image: $PHRASEANET_DOCKER_REGISTRY/phraseanet-fpm:$PHRASEANET_DOCKER_TAG
|
||||
restart: on-failure
|
||||
depends_on:
|
||||
@@ -29,6 +35,7 @@ services:
|
||||
- rabbitmq
|
||||
- elasticsearch
|
||||
environment:
|
||||
- PHRASEANET_PROJECT_NAME
|
||||
- MAX_BODY_SIZE
|
||||
- MAX_INPUT_VARS
|
||||
- OPCACHE_ENABLED
|
||||
@@ -57,6 +64,9 @@ services:
|
||||
build:
|
||||
context: .
|
||||
target: phraseanet-worker
|
||||
args:
|
||||
- SSH_PRIVATE_KEY=${PHRASEANET_SSH_PRIVATE_KEY}
|
||||
- PHRASEANET_PLUGINS=${PHRASEANET_PLUGINS}
|
||||
image: $PHRASEANET_DOCKER_REGISTRY/phraseanet-worker:$PHRASEANET_DOCKER_TAG
|
||||
restart: on-failure
|
||||
depends_on:
|
||||
@@ -65,6 +75,7 @@ services:
|
||||
- rabbitmq
|
||||
- elasticsearch
|
||||
environment:
|
||||
- PHRASEANET_PROJECT_NAME
|
||||
- MAX_BODY_SIZE
|
||||
- MAX_INPUT_VARS
|
||||
- OPCACHE_ENABLED
|
||||
|
@@ -0,0 +1,7 @@
|
||||
local ret_status="%(?:%{$fg_bold[green]%}➜ :%{$fg_bold[red]%}➜ %s)"
|
||||
PROMPT='%* %{$fg_bold[green]%}%n%{$fg[grey]%}@%m%{$fg_bold[green]%}%u ${ret_status}%{$fg_bold[green]%}%p %{$fg[cyan]%}%c %{$fg_bold[blue]%}$(git_prompt_info)%{$fg_bold[blue]%} % %{$reset_color%}'
|
||||
|
||||
ZSH_THEME_GIT_PROMPT_PREFIX="[%{$fg[red]%}"
|
||||
ZSH_THEME_GIT_PROMPT_SUFFIX="%{$reset_color%}"
|
||||
ZSH_THEME_GIT_PROMPT_DIRTY="%{$fg[blue]%}] %{$fg[yellow]%}✗%{$reset_color%}"
|
||||
ZSH_THEME_GIT_PROMPT_CLEAN="%{$fg[blue]%}]"
|
56
docker/builder/root/bootstrap/.zshrc
Normal file
56
docker/builder/root/bootstrap/.zshrc
Normal file
@@ -0,0 +1,56 @@
|
||||
export LC_ALL=en_US.UTF-8
|
||||
export LANG=en_US.UTF-8
|
||||
|
||||
export ZSH=$HOME/.oh-my-zsh
|
||||
|
||||
ZSH_THEME="alchemy"
|
||||
|
||||
# Uncomment the following line to use case-sensitive completion.
|
||||
# CASE_SENSITIVE="true"
|
||||
|
||||
# Uncomment the following line to use hyphen-insensitive completion. Case
|
||||
# sensitive completion must be off. _ and - will be interchangeable.
|
||||
# HYPHEN_INSENSITIVE="true"
|
||||
|
||||
# Uncomment the following line to disable bi-weekly auto-update checks.
|
||||
# DISABLE_AUTO_UPDATE="true"
|
||||
|
||||
# Uncomment the following line to change how often to auto-update (in days).
|
||||
# export UPDATE_ZSH_DAYS=13
|
||||
|
||||
# Uncomment the following line to disable colors in ls.
|
||||
# DISABLE_LS_COLORS="true"
|
||||
|
||||
# Uncomment the following line to disable auto-setting terminal title.
|
||||
# DISABLE_AUTO_TITLE="true"
|
||||
|
||||
# Uncomment the following line to enable command auto-correction.
|
||||
# ENABLE_CORRECTION="true"
|
||||
|
||||
# Uncomment the following line to display red dots whilst waiting for completion.
|
||||
# COMPLETION_WAITING_DOTS="true"
|
||||
|
||||
# Uncomment the following line if you want to disable marking untracked files
|
||||
# under VCS as dirty. This makes repository status check for large repositories
|
||||
# much, much faster.
|
||||
# DISABLE_UNTRACKED_FILES_DIRTY="true"
|
||||
|
||||
# Uncomment the following line if you want to change the command execution time
|
||||
# stamp shown in the history command output.
|
||||
# The optional three formats: "mm/dd/yyyy"|"dd.mm.yyyy"|"yyyy-mm-dd"
|
||||
# HIST_STAMPS="mm/dd/yyyy"
|
||||
|
||||
# Would you like to use another custom folder than $ZSH/custom?
|
||||
# ZSH_CUSTOM=/path/to/new-custom-folder
|
||||
|
||||
# Which plugins would you like to load? (plugins can be found in ~/.oh-my-zsh/plugins/*)
|
||||
# Custom plugins may be added to ~/.oh-my-zsh/custom/plugins/
|
||||
# Example format: plugins=(rails git textmate ruby lighthouse)
|
||||
# Add wisely, as too many plugins slow down shell startup.
|
||||
plugins=(git symfony2)
|
||||
|
||||
# User configuration
|
||||
|
||||
source $ZSH/oh-my-zsh.sh
|
||||
|
||||
alias ll='ls -alFh'
|
5
docker/builder/root/bootstrap/entrypoint.d/ohmyzsh.sh
Normal file
5
docker/builder/root/bootstrap/entrypoint.d/ohmyzsh.sh
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ ! -d "$HOME/.oh-my-zsh" ]; then
|
||||
cp -r "/bootstrap/.oh-my-zsh" "$HOME/.oh-my-zsh"
|
||||
fi
|
7
docker/builder/root/bootstrap/entrypoint.d/zshrc.sh
Normal file
7
docker/builder/root/bootstrap/entrypoint.d/zshrc.sh
Normal file
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
ZSH_FILE="$HOME/.zshrc"
|
||||
|
||||
if [ ! -f "$HOME/.zshrc" ]; then
|
||||
cp "/bootstrap/.zshrc" "$HOME/.zshrc"
|
||||
fi
|
17
docker/builder/root/bootstrap/entrypoint.sh
Executable file
17
docker/builder/root/bootstrap/entrypoint.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ -d /bootstrap/entrypoint.d ]; then
|
||||
for i in /bootstrap/entrypoint.d/*.sh; do
|
||||
if [ -r $i ]; then
|
||||
. $i
|
||||
fi
|
||||
done
|
||||
unset i
|
||||
fi
|
||||
|
||||
if [ ! -t 1 ] ; then
|
||||
echo "No tty available."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
exec "$@"
|
@@ -26,4 +26,6 @@ if [ ${XDEBUG_ENABLED} == "1" ]; then
|
||||
docker-php-ext-enable xdebug
|
||||
fi
|
||||
|
||||
./docker/phraseanet/plugins/console init
|
||||
|
||||
bash -e docker-php-entrypoint $@
|
||||
|
@@ -935,7 +935,7 @@ cli_server.color = On
|
||||
[Date]
|
||||
; Defines the default timezone used by the date functions
|
||||
; http://php.net/date.timezone
|
||||
date.timezone = Europe/Paris
|
||||
date.timezone = UTC
|
||||
|
||||
; http://php.net/date.default-latitude
|
||||
;date.default_latitude = 31.7667
|
||||
|
29
docker/phraseanet/plugins/InitCommand.php
Normal file
29
docker/phraseanet/plugins/InitCommand.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Alchemy\Docker\Plugins\Command;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class InitCommand extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('init')
|
||||
->setDescription('Initialize plugins');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
foreach (glob('./plugins/*') as $dir) {
|
||||
if (is_dir($dir)) {
|
||||
$output->writeln(sprintf('Init <info>%s</info> plugin', basename($dir)));
|
||||
SubCommand::run(sprintf('bin/setup plugin:add %s', $dir));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
64
docker/phraseanet/plugins/InstallCommand.php
Normal file
64
docker/phraseanet/plugins/InstallCommand.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Alchemy\Docker\Plugins\Command;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class InstallCommand extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('install')
|
||||
->setDescription('Install plugins');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$plugins = trim(getenv('PHRASEANET_PLUGINS'));
|
||||
if (empty($plugins)) {
|
||||
$output->writeln('<comment>No plugin to install... SKIP</comment>');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
$pluginsDir = 'plugins';
|
||||
if (!is_dir($pluginsDir)) {
|
||||
mkdir($pluginsDir);
|
||||
}
|
||||
|
||||
foreach (explode(' ', $plugins) as $key => $plugin) {
|
||||
$plugin = trim($plugin);
|
||||
$repo = $plugin;
|
||||
$branch = 'master';
|
||||
if (1 === preg_match('#^(.+)\(([^)]+)\)$#', $plugin, $matches)) {
|
||||
$repo = $matches[1];
|
||||
$branch = $matches[2];
|
||||
}
|
||||
|
||||
$pluginPath = './plugin' . $key;
|
||||
if (is_dir($pluginPath)) {
|
||||
SubCommand::run(sprintf('rm -rf %s', $pluginPath));
|
||||
}
|
||||
|
||||
$output->writeln(sprintf('Installing <info>%s</info> (branch: <info>%s</info>)', $repo, $branch));
|
||||
SubCommand::run(sprintf('git clone --single-branch --branch %s %s %s', $branch, $repo, $pluginPath));
|
||||
|
||||
$manifestSrc = $pluginPath.'/manifest.json';
|
||||
if (!file_exists($manifestSrc)) {
|
||||
throw new \Exception(sprintf('Cannot install plugin %s: no manifest.json file found', $plugin));
|
||||
}
|
||||
$pluginDestName = json_decode(file_get_contents($manifestSrc), true)['name'];
|
||||
rename($pluginPath, $pluginsDir.'/'.$pluginDestName);
|
||||
$pluginPath = $pluginsDir.'/'.$pluginDestName;
|
||||
|
||||
if (file_exists($pluginPath.'/composer.json')) {
|
||||
SubCommand::run(sprintf('cd %s && composer install --no-dev', $pluginPath));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
26
docker/phraseanet/plugins/SubCommand.php
Normal file
26
docker/phraseanet/plugins/SubCommand.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Alchemy\Docker\Plugins\Command;
|
||||
|
||||
function setupStreaming()
|
||||
{
|
||||
ini_set('output_buffering', 'off');
|
||||
ini_set('zlib.output_compression', false);
|
||||
if (function_exists('apache_setenv')) {
|
||||
apache_setenv('no-gzip', '1');
|
||||
apache_setenv('dont-vary', '1');
|
||||
}
|
||||
}
|
||||
|
||||
setupStreaming();
|
||||
|
||||
abstract class SubCommand
|
||||
{
|
||||
static public function run($cmd)
|
||||
{
|
||||
system($cmd, $return);
|
||||
if (0 !== $return) {
|
||||
throw new \Exception(sprintf('Error %d: %s', $return, $cmd));
|
||||
}
|
||||
}
|
||||
}
|
17
docker/phraseanet/plugins/console
Executable file
17
docker/phraseanet/plugins/console
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
namespace Alchemy\Docker\Plugins\Command;
|
||||
|
||||
require __DIR__.'/../../../vendor/autoload.php';
|
||||
require __DIR__.'/SubCommand.php';
|
||||
require __DIR__.'/InstallCommand.php';
|
||||
require __DIR__.'/InitCommand.php';
|
||||
|
||||
use Symfony\Component\Console\Application;
|
||||
|
||||
$application = new Application();
|
||||
|
||||
$application->add(new InstallCommand());
|
||||
$application->add(new InitCommand());
|
||||
|
||||
$application->run();
|
@@ -15,4 +15,4 @@ if [ ${XDEBUG_ENABLED} == "1" ]; then
|
||||
docker-php-ext-enable xdebug
|
||||
fi
|
||||
|
||||
runuser -u app "$@"
|
||||
runuser -u app -- $@
|
||||
|
@@ -15,6 +15,21 @@ use Alchemy\Phrasea\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
function normalizePath($path) {
|
||||
return array_reduce(explode('/', $path), function ($a, $b) {
|
||||
if($a === 0)
|
||||
$a = '/';
|
||||
|
||||
if($b === '' || $b === '.')
|
||||
return $a;
|
||||
|
||||
if($b === '..')
|
||||
return dirname($a);
|
||||
|
||||
return preg_replace('/\/+/', '/', "$a/$b");
|
||||
}, 0);
|
||||
}
|
||||
|
||||
abstract class AbstractPluginCommand extends Command
|
||||
{
|
||||
protected function validatePlugins(InputInterface $input, OutputInterface $output)
|
||||
@@ -54,33 +69,42 @@ abstract class AbstractPluginCommand extends Command
|
||||
|
||||
protected function doInstallPlugin($source, InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$temporaryDir = $this->container['temporary-filesystem']->createTemporaryDirectory();
|
||||
|
||||
$output->write("Importing <info>$source</info>...");
|
||||
$this->container['plugins.importer']->import($source, $temporaryDir);
|
||||
$output->writeln(" <comment>OK</comment>");
|
||||
|
||||
$output->write("Validating plugin...");
|
||||
$manifest = $this->container['plugins.plugins-validator']->validatePlugin($temporaryDir);
|
||||
$manifest = $this->container['plugins.plugins-validator']->validatePlugin($source);
|
||||
$output->writeln(" <comment>OK</comment> found <info>".$manifest->getName()."</info>");
|
||||
|
||||
$targetDir = $this->container['plugin.path'] . DIRECTORY_SEPARATOR . $manifest->getName();
|
||||
if (normalizePath($targetDir) !== normalizePath($source)) {
|
||||
$temporaryDir = $this->container['temporary-filesystem']->createTemporaryDirectory();
|
||||
$output->write("Importing <info>$source</info>...");
|
||||
$this->container['plugins.importer']->import($source, $temporaryDir);
|
||||
$output->writeln(" <comment>OK</comment>");
|
||||
$workingDir = $temporaryDir;
|
||||
} else {
|
||||
$workingDir = $targetDir;
|
||||
}
|
||||
|
||||
$output->write("Setting up composer...");
|
||||
$this->container['plugins.composer-installer']->install($temporaryDir);
|
||||
$output->writeln(" <comment>OK</comment>");
|
||||
if (!is_dir($workingDir.'/vendor')) {
|
||||
$output->write("Setting up composer...");
|
||||
$this->container['plugins.composer-installer']->install($workingDir);
|
||||
$output->writeln(" <comment>OK</comment>");
|
||||
}
|
||||
|
||||
$output->write("Installing plugin <info>".$manifest->getName()."</info>...");
|
||||
$this->container['filesystem']->mirror($temporaryDir, $targetDir);
|
||||
if (isset($temporaryDir)) {
|
||||
$this->container['filesystem']->mirror($temporaryDir, $targetDir);
|
||||
}
|
||||
$output->writeln(" <comment>OK</comment>");
|
||||
|
||||
$output->write("Copying public files <info>".$manifest->getName()."</info>...");
|
||||
$this->container['plugins.assets-manager']->update($manifest);
|
||||
$output->writeln(" <comment>OK</comment>");
|
||||
|
||||
$output->write("Removing temporary directory...");
|
||||
$this->container['filesystem']->remove($temporaryDir);
|
||||
$output->writeln(" <comment>OK</comment>");
|
||||
if (isset($temporaryDir)) {
|
||||
$output->write("Removing temporary directory...");
|
||||
$this->container['filesystem']->remove($temporaryDir);
|
||||
$output->writeln(" <comment>OK</comment>");
|
||||
}
|
||||
|
||||
$output->write("Activating plugin...");
|
||||
$this->container['conf']->set(['plugins', $manifest->getName(), 'enabled'], true);
|
||||
|
@@ -69,7 +69,7 @@ class AddPluginTest extends PluginCommandTestCase
|
||||
// the plugin is checked when updating config files
|
||||
self::$DI['cli']['plugins.plugins-validator']->expects($this->at(0))
|
||||
->method('validatePlugin')
|
||||
->with('tempdir')
|
||||
->with('TestPlugin')
|
||||
->will($this->returnValue($manifest));
|
||||
|
||||
self::$DI['cli']['plugins.plugins-validator']->expects($this->at(1))
|
||||
|
@@ -5305,10 +5305,14 @@ jquery-simplecolorpicker@^0.3.1:
|
||||
resolved "https://registry.yarnpkg.com/jquery-simplecolorpicker/-/jquery-simplecolorpicker-0.3.1.tgz#4f6befd380ab05470f585d5482e5180556e460eb"
|
||||
integrity sha1-T2vv04CrBUcPWF1UguUYBVbkYOs=
|
||||
|
||||
"jquery-treeview@git+https://github.com/alchemy-fr/jquery-treeview.git", "jquery-treeview@git+https://github.com/alchemy-fr/jquery-treeview.git#1e9e5a49d2875b878801e904cd08c2d25e85af1e":
|
||||
"jquery-treeview@git+https://github.com/alchemy-fr/jquery-treeview.git#1e9e5a49d2875b878801e904cd08c2d25e85af1e":
|
||||
version "1.4.2"
|
||||
resolved "git+https://github.com/alchemy-fr/jquery-treeview.git#1e9e5a49d2875b878801e904cd08c2d25e85af1e"
|
||||
|
||||
"jquery-treeview@https://github.com/alchemy-fr/jquery-treeview.git":
|
||||
version "1.4.2"
|
||||
uid "1e9e5a49d2875b878801e904cd08c2d25e85af1e"
|
||||
resolved "git+https://github.com/alchemy-fr/jquery-treeview.git#1e9e5a49d2875b878801e904cd08c2d25e85af1e"
|
||||
resolved "https://github.com/alchemy-fr/jquery-treeview.git#1e9e5a49d2875b878801e904cd08c2d25e85af1e"
|
||||
|
||||
jquery-ui-datepicker-with-i18n@^1.10.4:
|
||||
version "1.10.4"
|
||||
|
Reference in New Issue
Block a user