Le MakeFile parfait pour Symfony (au moins pour moi ! 😁)

PubliΓ© le 30/11/2018 • Mis Γ  jour le 21/04/2020


English language detected! πŸ‡¬πŸ‡§

  We noticed that your browser is using English. Do you want to read this post in this language?

Read the english version πŸ‡¬πŸ‡§ Close

J'ai toujours utilisΓ© des scripts shell (.sh) pour simplifier mes tΓ’ches de dΓ©veloppement pour mes projets Symfony. Mais j'ai rΓ©cemment dΓ©couvert (ici et ici) qu'il Γ©tait possible d'utiliser un Makefile. C'est vraiment beaucoup plus pratique que les scripts shell pour les raisons suivantes :

  • Γ‡a permet de documenter toutes les tΓ’ches de dΓ©veloppement dans un seul fichier.
  • On profite de l'autocomplΓ©tion des tΓ’ches puisque Make est un outil Unix standard.
  • Les erreurs sont interceptΓ©es et la tΓ’che principale est arrΓͺtΓ©e dΓ¨s qu'une erreur est dΓ©tectΓ©e dans une des sous tΓ’ches.

Le fichier Makefile que vous voyez ci dessous est celui qui est actuellement utilisΓ© pour ce projet Strangebuzz.com. Vous pouvez le tester pour voir la sortie par dΓ©faut de l'appel de la commande make. Cette sortie est la tΓ’che par dΓ©faut "aide" (help), qui liste toutes les tΓ’ches pouvant Γͺtre appelΓ©es. N'oubliez pas de changer le paramΓ¨tre PROJECT en haut du fichier πŸ˜‰. Le joli affichage de la sortie ANSI est fait Γ  l'aide de de la librairie sensiolabs/ansi-to-html.

[Maj 21/04/2020] Ajout des cibles pour Yarn / Webpack.
[Maj 07/03/2020] Affichage de la sortie console telle qu'elle apparait dans le terminal.
[Maj 19/12/2019] Ajout des cibles pour changer de version de PHP avec brew.
[BONUS] Le code PHP permettant de récupérer la sortie de l'appel système grÒce au composant Symfony Process et à la librairie ansi-to-html.


# β€”β€” Inspired by β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
# http://fabien.potencier.org/symfony4-best-practices.html
# https://speakerdeck.com/mykiwi/outils-pour-ameliorer-la-vie-des-developpeurs-symfony?slide=47
# https://blog.theodo.fr/2018/05/why-you-need-a-makefile-on-your-project/

# Setup β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
SHELL         = bash
PROJECT       = strangebuzz
EXEC_PHP      = php
REDIS         = redis-cli
GIT           = git
GIT_AUTHOR    = COil
SYMFONY       = $(EXEC_PHP) bin/console
SYMFONY_BIN   = symfony
COMPOSER      = $(EXEC_PHP) composer.phar
DOCKER        = docker-compose
BREW          = brew
.DEFAULT_GOAL = help
#.PHONY       = # Not needed for now

## β€”β€” 🐝 The Strangebuzz Symfony Makefile 🐝 β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
help: ## Outputs this help screen
	@grep -E '(^[a-zA-Z0-9_-]+:.*?##.*$$)|(^##)' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}{printf "\033[32m%-30s\033[0m %s\n", $$1, $$2}' | sed -e 's/\[32m##/[33m/'

wait: ## Sleep 5 seconds
	sleep 5

## β€”β€” Composer πŸ§™β€β™‚οΈ β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
install: composer.lock ## Install vendors according to the current composer.lock file
	$(COMPOSER) install --no-progress --no-suggest --prefer-dist --optimize-autoloader

update: composer.json ## Update vendors according to the composer.json file
	$(COMPOSER) update

## β€”β€” PHP 🐘 (macOS with brew) β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
php-upgrade: ## Upgrade PHP to the last version
	$(BREW) upgrade php

php-set-7-2: ## Set php 7.2 as the current PHP version
	$(BREW) unlink php@7.3 && brew unlink php@7.4
	$(BREW) link php@7.2 --force

php-set-7-3: ## Set php 7.3 as the current PHP version
	$(BREW) unlink php@7.2 && brew unlink php@7.4
	$(BREW) link php@7.3 --force

php-set-7-4: ## Set php 7.4 as the current PHP version
	$(BREW) unlink php@7.2 && brew unlink php@7.3
	$(BREW) link php@7.4 --force

## β€”β€” Symfony 🎡 β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
sf: ## List all Symfony commands
	$(SYMFONY)

cc: ## Clear the cache. DID YOU CLEAR YOUR CACHE????
	$(SYMFONY) c:c

warmup: ## Warmup the cache
	$(SYMFONY) cache:warmup

fix-perms: ## Fix permissions of all var files
	chmod -R 777 var/*

assets: purge ## Install the assets with symlinks in the public folder
	$(SYMFONY) assets:install public/ --symlink --relative

purge: ## Purge cache and logs
	rm -rf var/cache/* var/logs/*

## β€”β€” Symfony binary πŸ’» β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
bin-install: ## Download and install the binary in the project (file is ignored)
	curl -sS https://get.symfony.com/cli/installer | bash
	mv ~/.symfony/bin/symfony .

cert-install: symfony ## Install the local HTTPS certificates
	$(SYMFONY_BIN) server:ca:install

serve: ## Serve the application with HTTPS support
	$(SYMFONY_BIN) serve --daemon --port=8000

unserve: ## Stop the webserver
	$(SYMFONY_BIN) server:stop

# Snippet L70+12 => templates/blog/posts/_64.html.twig

## β€”β€” Elasticsearch πŸ”Ž β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
populate: ## Reset and populate the Elasticsearch index
	$(SYMFONY) fos:elastica:reset
	$(SYMFONY) fos:elastica:populate --index=app
	$(SYMFONY) strangebuzz:populate

# Snippet L86+4 => templates/blog/posts/_51.html.twig

list-index: ## List all indexes on the cluster
	curl http://localhost:9209/_cat/indices?v

delete-index: ## Delete a given index (replace "index" by the index name to delete)
	curl -X DELETE "localhost:9209/index?pretty"

## β€”β€” Docker 🐳 β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
up: docker-compose.yaml ## Start the docker hub (MySQL,redis,adminer,elasticsearch,head,Kibana)
	$(DOCKER) -f docker-compose.yaml up -d

docker-build: docker-compose.yaml ## UP+rebuild the application image
	$(DOCKER) -f docker-compose.yaml up -d --build

down: docker-compose.yaml ## Stop the docker hub
	$(DOCKER) down --remove-orphans

dpsn: ## List Docker containers for the project
	$(DOCKER) images
	@echo "--------------------------------------------------------------------------------------------------------------"
	docker ps -a | grep "sb-"
	@echo "--------------------------------------------------------------------------------------------------------------"

bash: ## Connect to the application container
	docker container exec -it sb-app bash

## β€”β€” Project 🐝 β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
run: up wait reload serve ## Start docker, load fixtures, populate the Elasticsearch index and start the webserver

reload: load-fixtures populate ## Reload fixtures and repopulate the Elasticserch index

abort: down unserve ## Stop docker and the Symfony binary server

cc-redis: ## Flush all Redis cache
	$(REDIS) -p 6389 flushall

commands: ## Display all commands in the project namespace
	$(SYMFONY) list $(PROJECT)

load-fixtures: ## Build the DB, control the schema validity, load fixtures and check the migration status
	$(SYMFONY) doctrine:cache:clear-metadata
	$(SYMFONY) doctrine:database:create --if-not-exists
	$(SYMFONY) doctrine:schema:drop --force
	$(SYMFONY) doctrine:schema:create
	$(SYMFONY) doctrine:schema:validate
	$(SYMFONY) doctrine:fixtures:load -n

init-snippet: ## Initialize a new snippet
	$(SYMFONY) $(PROJECT):init-snippet

## β€”β€” Tests βœ… β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
test: phpunit.xml ## Launch main functional and unit tests
	./vendor/bin/phpunit --testsuite=main --stop-on-failure

test-external: phpunit.xml ## Launch tests implying external resources (API, services...)
	./vendor/bin/phpunit --testsuite=external --stop-on-failure

test-all: phpunit.xml ## Launch all tests
	./vendor/bin/phpunit --stop-on-failure

## β€”β€” Coding standards ✨ β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
cs: codesniffer stan lint ## Launch check style and static analysis

codesniffer: ## Run php_codesniffer only
	./vendor/squizlabs/php_codesniffer/bin/phpcs --standard=phpcs.xml -n -p src/

stan: ## Run PHPStan only
	./vendor/bin/phpstan analyse -l max --memory-limit 1G -c phpstan.neon src/

psalm: ## Run psalm only
	./vendor/bin/psalm --show-info=false

init-psalm: ## Init a new psalm config file for a given level, it must be decremented to have stricter rules
	rm ./psalm.xml
	./vendor/bin/psalm --init src/ 3

cs-fix: ## Run php-cs-fixer and fix the code.
	./vendor/bin/php-cs-fixer fix src/

## β€”β€” Deploy & Prod πŸš€ β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
deploy: ## Full no-downtime deployment with EasyDeploy
	$(SYMFONY) deploy -v

env-check: ## Check the main ENV variables of the project
	printenv | grep -i app_

le-renew: ## Renew Let's Encrypt HTTPS certificates
	certbot --apache -d strangebuzz.com -d www.strangebuzz.com

## β€”β€” Yarn 🐱 / JavaScript β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
dev: ## Rebuild assets for the dev env
	yarn install
	yarn run encore dev

watch: ## Watch files and build assets when needed for the dev env
	yarn run encore dev --watch

build: ## Build assets for production
	yarn run encore production

lint: ## Lints Js files
	npx eslint assets/js --fix

## β€”β€” Stats πŸ“œ β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
stats: ## Commits by the hour for the main author of this project
	$(GIT) log --author="$(GIT_AUTHOR)" --date=iso | perl -nalE 'if (/^Date:\s+[\d-]{10}\s(\d{2})/) { say $$1+0 }' | sort | uniq -c|perl -MList::Util=max -nalE '$$h{$$F[1]} = $$F[0]; }{ $$m = max values %h; foreach (0..23) { $$h{$$_} = 0 if not exists $$h{$$_} } foreach (sort {$$a <=> $$b } keys %h) { say sprintf "%02d - %4d %s", $$_, $$h{$$_}, "*"x ($$h{$$_} / $$m * 50); }'
En bonus, le snippet permettant d'utiliser ce code : πŸŽ‰
<?php declare(strict_types=1);

namespace App\Controller\Snippet;

use SensioLabs\AnsiConverter\AnsiToHtmlConverter;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Process\Process;

/**
 * J'utilise un trait PHP afin d'isoler chaque snippet dans un fichier.
 * Ce code doit Γͺtre apellΓ© d'un contrΓ΄leur Symfony Γ©tendant AbstractController (depuis Symfony 4.2)
 * ou Symfony\Bundle\FrameworkBundle\Controller\Controller (Symfony <= 4.1).
 * Les services sont injectΓ©s dans le constructeur du contrΓ΄leur principal.
 *
 * @property KernelInterface $kernel
 *
 * @see https://github.com/sensiolabs/ansi-to-html
 */
trait Snippet8Trait
{
    public function snippet8(): void
    {
        $process = new Process([
            'make',
            '-f',
            $this->kernel->getProjectDir().'/Makefile',
        ]);
        $process->run();

        echo (new AnsiToHtmlConverter())->convert($process->getOutput()); // That's it! 😁
    }
}

 ExΓ©cuter le snippet  β‰ͺ this.showUnitTest ? this.trans.hide_unit_test : this.trans.show_unit_test ≫  Plus sur Stackoverflow   Lire la doc  Plus sur le web

<?php declare(strict_types=1);

namespace App\Tests\Controller\Snippets;

use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Process\Process;

/**
 * @covers Snippet
 */
final class Snippet8Test extends KernelTestCase
{
    protected function setUp(): void
    {
        self::bootKernel();
    }

    /**
     * @covers Snippet8Trait::snippet8
     *
     * @see https://www.strangebuzz.com/en/snippets/the-perfect-makefile-for-symfony
     */
    public function testSnippet8(): void
    {
        $process = new Process(['make', '-f', self::$kernel->getProjectDir().'/Makefile']);
        $process->run();
        $this->assertStringContainsStringIgnoringCase('The Strangebuzz Symfony Makefile', $process->getOutput());
    }
}