Magento2 extension development with Travis CI

If you have started developing a Magento2 shop with Composer you should have noticed that you will need some authentication keys. Alan Kent is explaining in his post Magento 2 and Composer Authentication why Magento thinks this is necessary. It doesn't make much sense to me why it is necessary also to store the open source extensions and modules in a protected repository, but I guess Magento is a control freak.

This protection is really a problem for maintaining open source extensions with Composer in a public continous integration. Today I would like to show how to use Travis CI for open source extensions with the password protected repository repo.magento.com from Magento2.

The scenario

Let us assume we have our Magento2 extension in a public Github repository with the following structure.

.
|-- Block/
|   `-- LayeredNavigation/
|       `-- RenderLayered.php
|-- etc/
|   |-- adminhtml/
|   |   `-- events.xml
|   |-- di.xml
|   `-- module.xml
|-- Helper/
|   `-- Data.php
|-- Model/
|   |-- Plugin/
|   |   |-- EavAttribute.php
|   |   `-- FilterRenderer.php
|   `-- AdvLayNav.php
|-- Observer/
|   |-- AddAdditionalValuesToAttributeObserver.php
|   `-- AddFieldsToAttributeObserver.php
|-- Test/
|   `-- Unit/
|       |-- Block/
|       |   `-- LayeredNavigation/
|       |       `-- RenderLayeredTest.php
|       |-- Helper/
|       |   `-- DataTest.php
|       |-- Model/
|       |   `-- Plugin/
|       |       |-- EavAttributeTest.php
|       |       `-- FilterRendererTest.php
|       |-- Observer/
|       |   |-- AddAdditionalValuesToAttributeObserverTest.php
|       |   `-- AddFieldsToAttributeObserverTest.php
|       `-- bootstrap.php
|-- view/
|   `-- frontend/
|       `-- templates/
|           `-- product/
|               `-- layered/
|                   `-- renderer.phtml
|-- composer.json
|-- .gitignore
|-- LICENSE.md
|-- phpunit.xml.dist
|-- README.md
|-- registration.php
`-- .travis.yml

This example is taken from PartBerlin/AdvLayNav. It is not really important what this extension does, more important is how we can run our PHPUnit tests in Travis CI. The file composer.json looks like this.

{
    "name": "part/advlaynav",
    "description": "Advanced Layered Navigation for Magento2",
    "license": "MIT",
    "repositories": [
        {
            "type": "composer",
            "url": "https://repo.magento.com/"
        }
    ],
    "require": {
        "php": "~5.6.0|~7.0.0",
        "magento/module-backend": "100.0.*",
        "magento/module-catalog": "100.0.*",
        "magento/module-eav": "100.0.*",
        "magento/module-layered-navigation": "100.0.*",
        "magento/framework": "100.0.*"
    },
    "require-dev": {
        "phpunit/phpunit": "^4.8",
        "phpmd/phpmd": "^2.3",
        "squizlabs/php_codesniffer": "^2.5",
        "sebastian/phpcpd": "^2.0",
        "satooshi/php-coveralls": "^1.0"
    },
    "type": "magento2-module",
    "version": "0.1.0",
    "autoload": {
        "files": [
            "registration.php"
        ],
        "psr-4": {
            "Part\\AdvLayNav\\": ""
        }
    }
}

We require magento/module-backend, magento/module-catalog, magento/module-eav, magento/module-layered-navigation and magento/framework. All these requirements are behind the password protected repository repo.magento.com. If we run composer install on your development environment, we have to give the username and password for the repository and Composer will store these credentials in an auth.json. Let us assume our .travis.yml would look like this.

language: php

sudo: false

php:
    - 5.6
    - 7.0

install:
    - composer install --prefer-dist

script:
    - php vendor/bin/phpcs --standard=PSR2 Block/ Helper/ Model/ Observer/ Test/
    - php vendor/bin/phpmd Block/,Helper/,Model/,Observer/,Test/ text cleancode,codesize,controversial,design,naming,unusedcode
    - php vendor/bin/phpcpd Block/ Helper/ Model/ Observer/ Test/
    - php vendor/bin/phpunit --coverage-clover build/logs/clover.xml

after_script:
    - php vendor/bin/coveralls

The problem

Since we can't put our auth.json into the public Github repository, we will get an error like this from Travis CI.

[Composer\Downloader\TransportException]
The 'https://repo.magento.com/packages.json' URL required authentication.
You must be using the interactive console to authenticate    

The solution

The solution is pretty easy. Travis CI has Encryption keys. The command line tool from Travis lets you create encrypted environment variables that can be used when the container runs. We just need to install the tool travis.

gem install travis

And now we can create encrypted environment variables MAGENTO_USERNAME and MAGENTO_PASSWORD. Please run the following command in the root of your repository or give the tool your Github user.

travis encrypt MAGENTO_USERNAME=[magento_username]
travis encrypt MAGENTO_PASSWORD=[magento_password]

After that we can put the output of both commands into our .travis.yml and we can build our auth.json file with the decrypted credentials before composer install.

language: php

sudo: false

php:
    - 5.6
    - 7.0

install:
    - echo "{\"http-basic\":{\"repo.magento.com\":{\"username\":\"${MAGENTO_USERNAME}\",\"password\":\"${MAGENTO_PASSWORD}\"}}}" > auth.json
    - composer install --prefer-dist

script:
    - php vendor/bin/phpcs --standard=PSR2 Block/ Helper/ Model/ Observer/ Test/
    - php vendor/bin/phpmd Block/,Helper/,Model/,Observer/,Test/ text cleancode,codesize,controversial,design,naming,unusedcode
    - php vendor/bin/phpcpd Block/ Helper/ Model/ Observer/ Test/
    - php vendor/bin/phpunit --coverage-clover build/logs/clover.xml

after_script:
    - php vendor/bin/coveralls

env:
    global:
        - secure: "DCvVwJnoZXUdbZpHD77EyL002dFJsTxE0WgcslY09mkffhWFTjc3pRKdUb25prAhwbkAJo5Pb6FS6GfqJmEJAs0R5mFBdvif0y9TCvrhy+5kpbnnnUJuQfK6dZ6VOPGfqtvGm0MENDtndr5dhyGHbZ9DSz3WBZIuieLdr/HKOS6MVKO9iIFLVn5ttIbpauwbAdAnHdIoyUSW7qqnbTIJsou9Yw3HbpSwKK2LtecqXVUh0Yu6n3YwpNjOBjvQ724u1tw6B4iKNWn5TCZBrYEYKA/knefSgw99ptEQIznDg42TlBp2Knqc9jluwtjxrbVwwA/0+pzGJ6ZI/lQ74akk6Cn41sr91dSO5eEqR8iL27OALCxpO0z/avI3PxBAC/btbEGTDCwMSXtzpHJ216o+p5Cb21qaDKy8PORo9XE7elInQK22Se04VhLICySCJ49sOCYRiXUISCbZzbLzuapDz5SaEEKm3gxdsfkeSE6L8dseyvie+zVRaG1C9dqlpnD8x/UclNOsT2F5vCrrE1Sk76IG/QHdy5naVX/eYyQo+0uIeFL3sD4S340XgxaXscHE8Dx9i0YnFSIlbk0yLvdVpV9/oG7QSuOfoBN2Ex28UCOUAXXq9kYimt9yXjcGcGarQqOPh9rPgHi93OYlqMphlVga8sg+C00+PRtbLvrPxJY="
        - secure: "sTmBL5CDHEmEmy7JSlbUmrM+EsT1m5iTsYUaScPAqYofn3T4vxyXQ3BlXsbOMrLxI33S+yoB54FWgOEa67nC4RTO20U6O3H9QjKOMdgMVTDmeoFohVOyOJSl3BXKPHOxTFf8/QPsz4sUziIftwObmFfrRD9nEPiMDF+YtI9TJW/tpEPiqjhYikz7OIPGD8d2z3RhHFHKdA41F66e0UZlPjR1+DNONiFy9xXHI4/rVDzlHQJFL1rVwPEMKDLznQRaz8DTl0+vqYCYdBwEZz3M6zekSpbFMUgdMSc8qLil+hVL7Rpgi1Rf4i7SRMKB0zI96gTwHFCD5c8cZgqKFx6I+hL7+0gQzCeoBG1Lm9KdtkzEBU4+boEOOkCy876xkOyP86J9HWfRxB7uQh6Ec2r4gSD9elTfiXiOZN+kwFhOHB6ypSq7qnFZ+YLo38SEAM2PysvE9sfOyohgg8eqccGBRiDgVWiSTguu3GekZxtSiUkvQUTkTmq2aHvNHEtD7pHKoCgNNn8PmOH+3ReMx+oQ7By2XJZlXCH7/vlhFhnxlPP++iLeFcpOu9tTRdzBKJ9TgL6PkDdpsmLFUAHKPl1KKugsWT+rYxYIlHvnc47CaH4210MfJKVKrNDDAL/jIpYG68IU3ecq+dkESsJHl6I3Y9HXlQdQD44MdmNz5hQrY4o="

Please note, this will make it impossible to run the tests on pull requests. If that would be possible, other users could just echo our password. But an limited continous integration is better that nothing in my eyes. After that composer install will get access to the repository repo.magento.com and we can start testing.

Next Previous