Building a phar – automated

I recently was asked whether JUnitDiff was available as a PHAR. Up to that point I hadn’t actually thought about it. But it made sense. The only thing I was sure about was that I didn’t want to have to think about it when doing a release. So the solution should fit nice into the build-chain.

Creating a PHAR from a composer-file via CLI

After initially looking into different tools (Thanks to Sebastian and Alessandro at that point) I decided to settle for phar-composer as it could easily create a PHAR-file using my already existing composer.json-file. No complicated setup, just a phar-composer.phar build <path/to/composer.json/folder> <path/to/target/folder> and that’s it. It might be somewhat messy in possibly integrating too much into the phar, but as it’s very easy to use I’ll neglect that.

To be able to handle that easily I decided to add the phar-creation to my composer.json. So I added this snippet:

{
    …
    &quot;scripts&quot;: {
        &quot;buildphar&quot; : [
            &quot;rm -rf vendor&quot;,
            &quot;composer install --no-dev --prefer-dist&quot;,
            &quot;curl -o phar-composer -L `curl -s https://api.github.com/repos/clue/phar-composer/releases | grep browser_download_url | head -n 1 | cut -d &#039;\&quot;&#039; -f 4`&quot;,
            &quot;chmod 755 phar-composer&quot;,
            &quot;chmod 755 phar-composer&quot;,
            &quot;mkdir ./build&quot;,
            &quot;./phar-composer build . build/&quot;
        ]
    }
}

The curl-line seems a bit strange at first sight, but I have to use the phar-file of phar-composer as integrating it via a composer require failed due to version-msimatch on the symfony console. So I need to get the download-link of the latest release from the github-API and download it.

Then a bit of unixy stuff to make it executable and execute it.

I choose to remove the whole vendor-folder and start fresh to not include the dev-tools in the binary as well.

So now I can call composer buildphar and find a working -phar-file in the build-folder. Awesome!

Include phar-creation into CI

The next step was to integrate that build into my CI. Currently I’m using travis and they trigger a build on tagging as well as on pushing and merging. That was what I wanted. Each time I tag a release it should cause travis to run the tests and then build the PHAR.

Turned out pretty easy as there is the Env-variable “TRAVIS_TAG” that contains the tag when it’s a build caused via committing a tag. So I needed to add some conditionals to the .travis-ci.yml like this:

matrix:
  include:
    …
    - php: 7.0
      env:
        …
        - BUILD_PHAR=true
    …

script:
  - composer test
  - if [[ $BUILD_PHAR == &#039;true&#039; &amp;&amp; $TRAVIS_TAG != &#039;&#039; ]]; then composer buildphar ; fi

…

So the composer buildphar will only be executed when the build was triggered via tagging and when we’re on PHP 7.0.
Great!

One step is missing though: The phar is created and then discarded as we don’t do anything…

Deploy to Github Releases

Thankfully the folks at travis already thought about that and created a deploy-mechanism. So all that was left to do was to add this to my .travis.yml:

deploy:
  provider: releases
  api_key: $GITHUB_API_KEY
  file: build/junitdiff.phar
  skip_cleanup: true
  on:
    tags: true
    php: &#039;7.0&#039;

Push the file build/junitdiff.phar to github-releases using the api-key (I added to the env-variables in the settings-panel). And this deployment is only run when the build was triggered by a tag and when the current PHP-version is PHP 7.0. That obviously needs to match the information from the composer.json.

Oh, and the skip_cleanup seems to be important as otherwise the build-folder might be cleaned before the deployment.

That’s it!

Now I can tag a new release in git and after pushing the tag to github it takes some minutes and I have a junitdiff.phar added to the release as downloadable file:

The only issue I had was the curl-command didn’t run on the first build so I had to manually trigger the build again. Then it worked exactly as expected. Not sure whether that was a network-timeout glitch or whatever…

Update 2017-01-20

I’ve moved from using phar-composer to using PharBuilder. The reason was mainly a better support for composer.json-values as the new lib doesn’t include everything but only the required autoloaded vendor-folders and – also in the composer.json – configurable folders. For the details have a look at the changes between 0.3.3 and 0.3.4