Continuous Integration (CI)
To help keep code quality and style consistent across projects we use a few developer tools that are installed locally per project and run by Github Actions on each Git push. You may check the Atlantis repo for a working example.
Composer scripts
Add the following to the composer.json
"scripts" property:
"eslint": "node_modules/.bin/eslint --ext .js resources/js/ --max-warnings=0",
"stylelint": "node_modules/.bin/stylelint resources/sass/**/*.scss",
"larastan": "vendor/bin/phpstan analyse",
"phpmd": "vendor/bin/phpmd app/ text phpmd.xml",
"phpcs": "vendor/bin/php-cs-fixer fix",
"phpunit": "php artisan test --parallel --stop-on-failure",
"test": [
"@eslint",
"@stylelint",
"@larastan",
"@phpunit"
]
Setup Github Actions
We use Github Actions on all new projects as our CI/CD pipeline. Github Actions is cheaper and faster than all other services and has a really powerful set of features.
To add Github Actions to a project, create a .github/workflows/tests.yml
file in the root of your project. This
is a typical example of a tests.yml
file:
name: CI
on: [push]
jobs:
tests:
name: Run PHP tests
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '--skip-ci')"
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install PHP 8.3
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
extensions:
coverage: none
- name: Setup Github token for private repos
run: composer config -g github-oauth.github.com ${{ secrets.GH_ACCESS_TOKEN }}
- name: Cache composer dependencies
uses: actions/cache@v4
with:
path: vendor
key: composer-${{ hashFiles('composer.lock') }}
- name: Install composer dependencies
run: composer install -n --prefer-dist --no-scripts --no-progress
- name: Setup locales
run: sudo locale-gen sv_SE.UTF-8
- name: Prepare Laravel
run: |
cp .env.example .env
php artisan key:generate
- name: Cache npm dependencies
uses: actions/cache@v4
with:
path: node_modules
key: npm-${{ hashFiles('package-lock.json') }}
- name: Run npm
run: npm ci
- name: Create database
run: |
sudo /etc/init.d/mysql start
mysql -u root -proot -e 'CREATE DATABASE app;'
- name: Run tests
run: composer test
env:
DB_DATABASE: app
DB_USERNAME: root
DB_PASSWORD: root
- name: Upload logs on failure
uses: actions/upload-artifact@master
if: failure()
with:
name: Logs
path: ./storage/logs
- name: Deploy prod if master
if: success() && github.ref == 'refs/heads/master' && !contains(github.event.head_commit.message, '--skip-deploy')
run: |
curl --silent --show-error --fail -X POST ${{ secrets.DEPLOY_PROD_URL }}
curl --silent --show-error --fail -X POST ${{ secrets.DEPLOY_STAGING_URL }}
Be sure to validate the file with an online YAML validator before pushing it to Github for the first time.
The GH_ACCESS_TOKEN
variable is an Organization secret personal access token (on the adaptivemachine
account) which gives composer read access to our private repos.
This is possible since the adaptivemachine
user is added to a Read
team which is added on all our private repos.
Every project is different and has different needs, but this is a good starting point. Check out our other repos for various examples.