Replace PHP Class Dependencies from Git Bash - php

I'm using Laravel 5.2 and a RethinkDB service provider that uses a different dependency than normally migrated files, which is all handled for you if you write your migrations manually, but we build up our migrations using http://www.laravelsd.com/. During initial development tweaks occur so I wanted to write a quick bash script to run through /data/migrations/*.php files and replace the dependency if newly export migrations are dropped in. So far I've tried a bunch of different solutions with no luck and tried augmenting them too.
This seemed like it should work to replace Illuminate\Database\Schema\Blueprint with duxet\Rethinkdb\Schema\Blueprint:
cd database/migrations
grep --include={*.php} -rnl './' -e "Illuminate\Database\Schema\Blueprint" | xargs -i# sed -i 's/Illuminate\Database\Schema\Blueprint/duxet\Rethinkdb\Schema\Blueprint/g' #
Any suggestions why this isn't working? I don't see anything else in --help that would be useful.

Related

WebdriverIO and Docker Setup

I am trying to setup a docker container with WebdriverIO built into it, with the eventual aim of being able to run a CI/CD pipeline in gitlab, but I have absolutely no idea where to start.
My application is a PHP/MySQL based app which was also recently dockerised. I access it locally on http://localhost.
I have tried to create a docker image with wdio built into it, but it fails when trying to do the
npm init wdio --yes
as the --yes command doesn't force any of the default settings, which goes against the official documentation. This then causes the wdio installation to fail.
What is confusing me even more is that there seems to be very few tutorials for this, the wdio documentation doesn't seem great, and what tutorials I can find all seem to mention selenium. FYI, I am just a dev that has been tasked to take some existing WDIO scripts and get them ready for CI/CD, I don't know a massive amount about WDIO in the first place.
Does anyone have any basic steps I could follow that would describe the process of taking some local WDIO scripts, and getting them to run inside a container, with the end goal of being to have them into some sort of CI/CD pipeline?
When trying to create the image, the following command does not seem to work:
npm init wdio --yes
It would be much more appropriate if you have initialize a wdio project and copy it to the Dockerfile.
This is what it might look like:
FROM node:16
USER root
#===============================
# Set default workspace
#===============================
RUN mkdir /home/workspace \
&& chmod 2777 /home/workspace
COPY . /home/workspace
WORKDIR /home/workspace
This way, your docker image contains your whole project built in.
Then you could append the following command to make sure the environment is ready for webdriverI/O to execute.
#==================================
# Install needed packages
#==================================
RUN apt update && apt upgrade -y
RUN npm install
If you need anything like browser and webdriver, you could install it via dozens of approaches.
You can use ENTRYPOINT or CMD to make it execute the specified test suites once the container is up.
If you wanna complete CI or CD flow with docker containers, it will depend on which service you may utilize.

Why despite "drush" being installed via `composer global install` during image build, I cannot find the tool from within a running PHP script?

I am developing a PHP web application inside of a Docker container. Using volumes: inside of my docker-compose.yml file, I have specified a local directory so that any files generated are dumped and persist after the container is destroyed.
volumes:
- ./docroot:/var/www/html
Inside my Dockerfile, I RUN a command that installs a command line management tool:
RUN curl -sS https://getcomposer.org/installer | php && \
mv composer.phar /usr/local/bin/composer && \
ln -s /root/.composer/vendor/bin/drush /usr/local/bin/drush
RUN composer global require drush/drush:8.3.3 && \
composer global update
When the container comes up, I can use docker-compose exec -it <container> bash to get inside the container, and everything works fine. drush is in my path, and I can use it globally throughout the container to manage the app.
Now here is the strange part. Part of my application is that I have to run that command from a PHP script inside the container to help automatically manage some of the build process.
Using php, I run exec('drush dbupdate', $output, $retval); $retval returns a exit status of 127, or command not found and $output is empty. If I switch up the exec to use the full path I get an exit status 126.
If I go back into the container, I can run that command just fine. Note all other cli commands work as expected with exec (ls, whoami, etc but which drush returns exist status 1)
What am I missing? Why can I use it with no problems manually, but PHP exec() can't find it? passthru(), shell_exec(), and others have the same behavior.
composer global install will not install the command "globally" for all users, but "globally" as in "for all projects".
Generally, these packages are installed in the home directory for the user executing the command (e.g. ~/.composer), and if they are available in your path is because ~/.composer/vendor/bin is added to the session path.
But when you run composer global require (while building the image) or when you "log in" to the running container (using exec [...] bash) the user involved is root. But when your PHP script runs, it's being executed by another user (presumably www-data). And for that user, ~/.composer does not contain anything.
Maybe do not install drush using composer, but rather download the PHAR file directly or something like that while you are building the image, and put it in /usr/local/bin.
If you are using Drupal >= 8, the recommended way of installing Drush is not as a "global" dependency, but as "project" dependency, so that the appropriate drush version is installed. This comes straight from the docs:
It is recommended that Drupal 8 sites be built using Composer, with Drush listed as a dependency. That project already includes Drush in its composer.json. If your Composer project doesn't yet depend on Drush, run composer require drush/drush to add it. After this step, you may call Drush via vendor/bin/drush

How to configure PHPUnit in MAMP with PHAR

I wanna test my php codes and I have decided to user PHPUnit for my test.
I have followed steps with official documentation
$ wget https://phar.phpunit.de/phpunit.phar
$ chmod +x phpunit.phar
$ sudo mv phpunit.phar /usr/local/bin/phpunit
$ phpunit --version
PHPUnit x.y.z by Sebastian Bergmann and contributors.
But I am using MAMP with my MacOS X.
So I am not sure how to implement PHAR files in MAMP.
Normally, the documentation tells to use this comment in terminal:
sudo mv phpunit.phar /usr/local/bin/phpunit
And my PHP location is:
/Applications/MAMP/bin/php/php5.2.17/bin/
I've tried to run this comment:
sudo mv phpunit.phar /Applications/MAMP/bin/php/php5.2.17/bin/
I don't know what should I do at this step. Please take a look because it does not work.
Here are the steps I used to successfully get PHPUnit working in MAMP. These instructions
are pieced together from various places. I hope that having it all in one place helps
someone else. Happy testing!
Use MAMP's PHP in the Terminal
Adapted from How to override the path of PHP to use the MAMP path?
Edit or create ~/.bash_profile with the lines below
# Use MAMP's latest version of PHP
MAMP_LATEST_PHP=`ls /Applications/MAMP/bin/php/ | sort -n | tail -1`
export PATH=/Applications/MAMP/bin/php/${MAMP_LATEST_PHP}/bin:$PATH
Place these lines after any other lines exporting $PATH - this assures that your MAMP PHP is found first in the path. Note that these lines try to find the highest numbered version of PHP in your MAMP installation. Feel free to adjust this to a specific one that you have, if desired.
You can tell you did it right when you get a MAMP path from which php in your terminal. You should get something like this:
/Applications/MAMP/bin/php/php7.0.0/bin/php
Install PHPUnit
Mostly, this is downloading the PHP archive (PHAR) from the PHPUnit website. There are ways to do this from the command line that I couldn't get to work. So, I used a web browser.
Download the most recent PHPUnit PHAR from https://phar.phpunit.de
Move it to /usr/local/bin
cd /usr/local/bin
Make it executable with chmod +x phpunit-5.3.2.phar (adjust according to actual name)
Make a symbolic link with ln -s phpunit-5.3.2.phar ./phpunit (adjust according to actual name)
Check the version with phpunit -—version
You should get something like this:
PHPUnit 5.3.2 by Sebastian Bergmann and contributors.
Building a symbolic link in step 5 permits you to use phpunit instead of having to type
phpunit-5.3.2.phar instead. It also allows you to update PHPUnit without having to
change what you type, assuming of course that you create a new symbolic link when you
update.
Write a Test
This isn't an exhaustive section. There are far better tutorials on writing tests.
Instead, this is merely some notes from my experience on rules that tripped me up,
though I'm sure everyone else knows them:
Your test class name must end with Test:
class SomeTest extends PHPUnit_Framework_TestCase
Your test class file name must end with Test.php and match the contained class:
SomeTest.php
Method names in your test class that are to be run as tests must start with test:
public function testSomething()
Run a Test
By this time, it should be as easy as:
phpunit SomeTest
If everything goes well, PHPUnit will run your test and give you the results.
Add a Handy Alias
Assuming that it all works (Yay!) try this alias in your ~/.bash_profile
# Use colors when running phpunit
alias phpunit='phpunit --colors'
/usr/local/bin/ is just recommended as a convention, because it's always in the $PATH on Unix systems, you can use any other location that's in your path, or leave it anywhere else and specify the absolute path when using it.
With what you have, you should be able to run:
/Applications/MAMP/bin/php/php5.2.17/bin/phpunit.phar --version
Note the .phar suffix, because you did not rename the file while moving, as you'd have with sudo mv phpunit.phar /usr/local/bin/phpunit
I tried. You can use this command. It worked for me.
sudo mv phpunit.phar /Applications/MAMP/bin/php/php5.2.17/bin/phpunit

Recommend way to Artisan on Docker

I am yet to find an elegant and efficient way to run Laravel Artisan commands in my Docker based local dev environment.
Could anybody suggest the recommended or "proper" way to do things like migrations?
Or, has anybody found a neat way of doing this? Ideally with examples or suggestions.
Things that I've considered:
A new container (sharing the same volume and db link) with ssh, just for running commands (seems nasty).
Hacks in supervisor that could then end up running on live (not ideal).
Editing db configs, or trying to hack in a "host" environment, so that at least things like migrate can be run from the host.
Creating web front ends to run things (really nasty).
Trying to build a "signal" for it things.
I'm still getting my head around Docker and it's new-container-for-everything approach.
I suppose I want to balance cool-dev-ops stuff with why-do-I-need-another-fake-server-just-get-it-working-already.
I'd love to commit to it for my dev workflow, but it seems to become awkward to use under certain circumstances, like this one...
Any suggestions and ideas are welcome. Thanks all.
Docker 1.3 bring new command exec
So now you can "enter" running container like
docker exec -it my-container-name /bin/bash
After that you can run any command you want
php artisan --version
The best practice regarding Docker is to run each process inside it's own container. Therefore, the ideal way to run artisan commands is to have an image for creating containers specifically for this purpose.
I've created an image which can be pulled from the Docker Hub dylanlindgren/docker-laravel-artisan and it works really well. It's on GitHub as well if you want to take a look at the Dockerfile behind it.
I've also just written a blog post describing the way that all these seperate containers fit together.
There are a couple of possibilities...
Mounting a host directory in your container as the folder in which your Laravel app lives. That way you can just run php artisan migrate or composer update from the host. You might have problems with deployment, though, since you would have to replicate that part of your environment on the server.
adding an SSH server to your container (which is not recommended; here's a good discussion of that).
build and use nsenter, a tool for "entering" a running container and getting shell access. Note, I haven't used it, I just found it a while ago via a reference in the link above.
If you're primarily interested in deployment and you're doing it via a dockerfile, then the answer would be to add composer install and php artisan migrate to your dockerfile so they run when the container is built.
I'm interested in hearing more answers to this. It's something that I'm just getting into as well and would like to learn more about.
I use SSH and run migrations from a terminal inside the container.
I personally like Phusion's approach of using Docker as a 'lightweight virtual machine'. So I used their baseimage-docker which I've extended to create my own Docker image for Laravel applications.
I'm aware Phusion's image can be contentious in the Docker community, and that SSH is frowned upon by some who advocate Docker containers as microservices. But I'm happy with Phusion's approach until there are more established tools and practices for the multi-container approach.
I'm in the process of figuring out creating Docker images for Laravel projects, this is what I have so far.
FROM base_image_with_LAMP_stack_and_dependencies
WORKDIR /var/www/html/app
COPY composer.json composer.json
RUN composer install --no-scripts --no-dev --no-autoloader
COPY . .
RUN echo 'chown -R www-data:www-data /var/www/ \
&& composer dump-autoload \
&& cp .env.example .env \
&& php artisan key:generate \
&& php artisan migrate \
&& apachectl -D FOREGROUND' >> /root/container_init.sh && \
chmod 755 /root/container_init.sh
EXPOSE 80
CMD /root/container_init.sh
This way, there is no dependency on database during build time, and the migration process can run every time a new container is started.

Run PHPUnit tests on change

I'd like to run my PHPUnit tests (or at least a subset of them) whenever a file changes on disk. Very similar to what you can do with "grunt watch". I have a project in which I have both JS and PHP, and am using Grunt. There I shell out to PHPUnit to have it run on top of my JS tests using grunt watch. While that works just fine, it seems like an awful lot of hassle to do this in a PHP only project. I'd need to introduce grunt, and add a dependency on node. Plus I have a lot of such PHP projects. A more simple solution is thus in order.
You can use node watch which is quite sweet:
Run npm init to set up a package (takes a minute), then
npm install --save-dev watch
Then edit your package.json file to include these two entries:
"scripts": {
"test": "bin/phpunit tests --color",
"test:watch": "watch 'npm run --silent test' ."
},
Then trigger the watching with:
npm run test:watch
(credit due to this interesting article)
I've wrote a blog post on this a while back: http://edorian.github.io/2010-03-11-running-your-unit-tests-everytime-you-save-a-file/
The most basic command would be:
pywatch phpunit .
which would mean "monitor all files in this directory and below for changes and if one of them changes run PHPUnit".
If you have a lot of files in there (assets etc) that can get slow so a better/faster version is:
find -name '*.php' | xargs pywatch "./runSuite.sh"
which only monitors changes to .php files
Maybe you can try phpunit-watcher. https://packagist.org/packages/spatie/phpunit-watcher
First, to install phpunit-watcher with composer require spatie/phpunit-watcher --dev, and then, modify the composer.json to add an item in scripts property:
{
"scripts" : {
"test" : "./vendor/bin/phpunit-watcher watch --bootstrap vendor/autoload.php tests/"
}
}
Then, you can run test cases with: composer test.
Sometimes, you should run composer run test --timeout=0, otherwise the process would be killed after 300 seconds.
In PHPStorm you can configure File Watcher that will execute shell commands for you at file modifications. For example you can have one File Watcher that will trigger on php file modification and will run phpunit command with all necessary commands.
More info about File Watchers can be found on JetBrains web help page: https://www.jetbrains.com/phpstorm/webhelp/using-file-watchers.html
A dead simple way to do this, using inotifywait and a bash script:
#!/bin/bash
while true; do
FILE=$(inotifywait --exclude=".*.*sw*" --exclude="4913" ./ --format "%w%f" -e close_write) &&
clear &&
phpunit --color $FILE
done
Then you just run that in a terminal (or however you want) and you're good. I'm running tmux, so I just have a stacked pane set up, with a little window to see my test results. Just run this script in the directory where your tests live.
Works well for me.
Also, this script is Vim friendly (Vim creates a file, 4913, during saves, this script ignores it).
It was totally inspired from various places around the web -- probably even from some of these answers.
Install grunt and use https://github.com/SaschaGalley/grunt-phpunit
Then you'd setup the phpunit task under with the watch task. This is how I do it right now.
I've created a solution to deal with this very problem: "What's Changed?" In short, there are cases where you have some really large test suites and you only want to run the tests relevant to the classes which have changed.
You can pull this in via composer by running composer require --dev icyapril/whats-changed
With this in place just run ./vendor/bin/whatschanged and only the file changed in your last commit or in your working directory will be run. Magic!
You can use inotifywait, see https://speakerdeck.com/rowan_m/building-better-developers-2?slide=31 for a PHPUnit example.
I found the phpunit-testrunner node package, which is of use for my problem. One config json file per PHP project, which can then be used by anyone that has the node package installed. Also cross platform. Still requires node though, so not an ideal solution.
i found this solution use node+gulp
0. install node
1. npm init
2. npm install gulp --save-dev
create a gulpfile.js and put this
var gulp = require('gulp'),
util = require('util'),
exec = require('child_process').exec;
gulp.task('phpunit', function() {
exec('phpunit -c my_project_name/App', function(error, stdout) {
util.puts(stdout);
});
});
gulp.task('default',['phpunit'], function() {
gulp.watch('my_project_name/**/*.php', ['phpunit']);
});
my_project_name/App is the path of all source code
if add extension add this line on default task
gulp.watch('my_project_name//*.otherext', ['phpunit']);
after edit php file run the phpunit test

Categories