Selenium testing PHP sites in Bitbucket Pipelines

It looks like mounting files isn’t possible in the bitbucket services without getting all meta and using custom Docker-in-Docker images, so I ended up ditching the nginx service. However I successfully managed to run the PHP built in webserver!

php -S 127.0.0.1:80 public/index.php &

The -S option starts the built in dev server, and public/index.php is my app’s entrypoint. The & pushes the process into the background. It only seems to work with the 127.0.0.1 IP, if you try a custom host it won’t work.

Here’s my full pipeline config:

image:
  name: php:8.1-fpm
  username: $DH_USER
  password: $DH_PASS

definitions:
  services:
    db:
      image: mariadb:10.2
      variables:
        MARIADB_DATABASE: MY_TEST_DB
        MARIADB_USER: root
        MARIADB_ROOT_PASSWORD: 'root'
    chrome:
      image: selenium/standalone-chrome
      ports:
        - 4444
        - 5900


pipelines:
  pull-requests:
    '**':
      - step:
          services:
            - db
            - chrome
          name: Installing Composer and running Unit Tests...
          script:
            - if [[ "${BITBUCKET_PR_DESTINATION_BRANCH}" != "develop" ]] && [[ "${BITBUCKET_PR_DESTINATION_BRANCH}" != "release/"* ]]; then printf "Skipping Tests for this target (${BITBUCKET_PR_DESTINATION_BRANCH})"; exit; fi
            - curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
            - composer install --no-scripts
            - vendor/bin/grumphp git:pre-commit
            - cp config/autoload/data.test.php.dist config/autoload/data.test.php
            - php bin/console orm:schema-tool:create
            - php bin/console fixtures:load
            - php -S 127.0.0.1:80 public/index.php &
            - vendor/bin/codecept run --env=bitbucket

  branches:
    develop:
      - step:
          services:
            - db
          name: Installing Composer and running Unit Tests...
          script:
            - curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
            - composer install --no-scripts
            - vendor/bin/grumphp git:pre-commit
            - cp config/autoload/data.test.php.dist config/autoload/data.test.php
            - php bin/console orm:schema-tool:update --force --complete
            - php bin/console fixtures:load
            - php -S 127.0.0.1:80 public/index.php &
            - vendor/bin/codecept run unit --env=bitbucket

Auto prepend a JIRA ticket number to your commit messages

To ensure commit messages contain the JIRA ticket, in the following format:

ABC-1234 : [your commit message here]

You can have this prepended automatically by creating `.git/hooks/prewpare-commit-msg`, with the following code:

#!/bin/sh
COMMIT_MSG_FILE=$1
branch=$(git branch --show-current)
issue=$(sed -e 's/.*\/\([A-Z]\{3\}-[0-9]\{4\}\)\/.*/\1/' <<< $branch)

if [[ $issue =~ [A-Z]{3}-[0-9]{4} ]]; then
originalText=$(cat "$COMMIT_MSG_FILE")
echo "$issue : " > "$COMMIT_MSG_FILE"
echo "$originalText" >> "$COMMIT_MSG_FILE"
fi

After creating the file, run `chmod +x .git/hooks/prepare-commit-msg` to make it executable.

You should also have a `commit-msg` hook to check with regex that the first line contains more than just the ticket
[A-Z]{3}-[0-9]{4}\s:\s(.*). Exit with a non zero status if the regex fails

In my case I am using GrumPHP to manage the commit-msg hook. GrumPHP has a JIRA ticket task, which we can set up in the yaml file like so:

  tasks:
    git_commit_message:
      matchers:
        Must contain JIRA issue number: '/[A-Z]{3}-[0-9]{4} : (.+)/'

Stop git committing chmod changes

Pretty self explanatory. Just do this:

git config core.fileMode false

The documentation says this about it:

core.fileMode 
If false, the executable bit differences between the index and the 
working copy are ignored; useful on broken filesystems like FAT. 
See git-update-index(1). True by default.

Here’s a warning from a guy on StackOverflow:

core.fileMode is not the best practice and should be used carefully. This setting only covers the executable bit of mode and never the read/write bits. In many cases you think you need this setting because you did something like chmod -R 777, making all your files executable. But in most projects most files don’t need and should not be executable for security reasons.

The proper way to solve this kind of situation is to handle folder and file permission separately, with something like:

find . -type d -exec chmod a+rwx {} \; # Make folders traversable and read/write
find . -type f -exec chmod a+rw {} \; # Make files read/write

If you do that, you’ll never need to use core.fileMode, except in very rare environment.

Line Endings in Git with Windows

Devving on Windows is a PITA.

Anyway, ever seen a message like this?

warning: LF will be replaced by CRLF in tests/unit/Del/Console/CommandTest.php.
The file will have its original line endings in your working directory.
warning: LF will be replaced by CRLF in tests/unit/Del/Console/CommandTest.php.
The file will have its original line endings in your working directory.

We only want LF. To squelch this crap, run the following:

git config core.autocrlf false

Yay.

Use Git bisect to find dodgy commits

Today I had the mammoth task of checking through 512 git commits to find a piece of code that broke something.

Usually i would git log, look back however many commits, and then do a git reset –hard COMMIT_NUMBER, then check if it worked. If it did, I would git pull back to the HEAD again, and try a resetting back to a more recent commit, until I found the bad code.

Never again! Git bisect to the rescue!

Find any good commit in the past, and note the commit number. Find any bad commit where the code is broken, and note the commit number.

Now, do the following:

git bisect start
git bisect good 514d83c
git bisect bad b27f38e

capture

Git checks out the middle commit between the good and bad ones. At this point I reloaded my page to see if the code was working or not. The code was working, so I then told git that it was good:

git bisect good

capture

Again the code was working, so as you can see I ran it again. Each time, git bisect jumps half way, iterating and narrowing down the options. Keep doing this and checking your code until it breaks, then say:

git bisect bad

Here’s the rest of the output:

capture

Now we have the exact commit number, and can do a git diff to find out what you did wrong! 🙂

Once you have the commit in question, tell git bisect that you are finished:

git bisect reset

I am amazed that I’m only just finding out about this awesome feature of Git! I’m sure you’ll love it too, try it!

Have fun!

Updating a forked GitHub Repo

At the PHPNW 2014 conference, they had a ‘Hackathon’, where everyone got together and started hacking away at projects. I had a shot at the JoindIn website.

Anyway, I forked the repositories so I could work on my own branch. Now though, my fork is outdated, and needs updating. So in order to remedy this, we add another remote.

From your local machine’s cloned repo, you simply say:

git remote add upstream https://github.com/joindin/joindin-web2.git
git checkout master
git pull upstream master
git push origin master

Thanks to Derick Rethans of XDebug fame for this info 😀