GitHub acquires npm

It was suggested that Microsoft/GitHub should have bought npm back in the day, instead of launching their own registry. Today is the day they’ve actually done it:

We at GitHub are honored to be part of the next chapter of npm’s story and to help npm continue to scale to meet the needs of the fast-growing JavaScript community.

For the millions of developers who use the public npm registry every day, npm will always be available and always be free. Looking further ahead, we’ll integrate GitHub and npm to improve the security of the open source software supply chain, and enable you to trace a change from a GitHub pull request to the npm package version that fixed it.

npm is joining GitHub →

Getting started with GitHub Actions and Laravel (~PHP)

Ruben Van Assche from Spatie:

When GitHub released its new product: GitHub Actions a whole new world opened for developers. Let’s dive right in and see what it brings for the Laravel community.

In How to set up PHP for use in a GitHub Action I’ve layed out how to use shivammathur/setup-php@v1 in GitHub Actions. This post goes very nicely along with it. Recommended read, even if you don’t write Laravel (like me).

I especially like the part where an extra MySQL service is spun up from within the workflow, and then used in the tests.

// ...

jobs:
    tests:
        // ...

        services:
            mysql:
                image: mysql:5.7
                env:
                    MYSQL_ALLOW_EMPTY_PASSWORD: yes
                    MYSQL_DATABASE: our-awesome-tested-app
                ports:
                    - 3306
                options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
                
        // ...

Getting started with GitHub Actions and Laravel →

How to set up PHP for use in a GitHub Action

To use PHP in a GitHub action there’s the magnificent setup-php action. It also allows for installing extensions and setting several php.ini directives.

steps:
- name: Checkout
  uses: actions/checkout@v1

- name: Setup PHP
  uses: shivammathur/setup-php@v1
  with:
    php-version: '7.4'
    extensions: mbstring, intl #optional, setup extensions
    ini-values: post_max_size=256M, short_open_tag=On #optional, setup php.ini configuration
    coverage: xdebug #optional, setup coverage driver
    pecl: false #optional, setup PECL

Here’s an example that uses a build matrix:

jobs:
  run:    
    runs-on: ${{ matrix.operating-system }}
    strategy:      
      matrix:
        operating-system: [ubuntu-latest, windows-latest, macOS-latest]
        php-versions: ['7.0', '7.1', '7.2', '7.3', '7.4']
    name: PHP ${{ matrix.php-versions }} Test on ${{ matrix.operating-system }}
    steps:
    - name: Checkout
      uses: actions/checkout@v1

    - name: Setup PHP
      uses: shivammathur/setup-php@v1
      with:
        php-version: ${{ matrix.php-versions }}
        extensions: mbstring, intl #optional, setup extensions
        ini-values: post_max_size=256M, short_open_tag=On #optional, setup php.ini configuration
        coverage: xdebug #optional, setup coverage driver
        pecl: false #optional, setup PECL

When building against a matrix, the documentation recommends to cache composer data to speed up the process.

shivammathur/setup-php

💡 This example workflow from Spatie’s laravel-fractal Pacakge is also worth a peek. Also builds against a matrix with caching, but in a slightly different way.

Use a Github repository branch or commit as a dependency in package.json

Recently I needed to test a branch of a forked GitHub repository inside a project. Instead of cloning the fork and symlinking the package locally, I installed the remote dependency directly into the project.

To achieve I used the following command:

Using NPM:

npm install user/repo.git#branchname

Using Yarn:

yarn add ssh://git@github.com:user/repo.git#branchname

💡 If you’re targeting a specific commit or tag, replace branchname with the commmithash or tagname

Did this help you out? Like what you see?
Thank me with a coffee.

I don't do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

☕️ Buy me a Coffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

GitHub CI Workflow for PHP applications

Mattias Geniar has shared his GitHub Workflow to make GitHub do the CI work for PHP applications:

on: push
name: Run phpunit testsuite
jobs:
  phpunit:
    runs-on: ubuntu-latest
    container:
      image: mattiasgeniar/php73

    steps:
    - uses: actions/checkout@v1
      with:
        fetch-depth: 1

    - name: Install composer dependencies
      run: |
        composer install --prefer-dist --no-scripts -q -o;
    - name: Prepare Laravel Application
      run: |
        cp .env.example .env
        php artisan key:generate
    - name: Compile assets
      run: |
        yarn install --pure-lockfile
        yarn run production --progress false
    - name: Set custom php.ini settings
      run: echo 'short_open_tag=off' >> /usr/local/etc/php/php.ini
    - name: Run Testsuite
      run: vendor/bin/phpunit tests/

Tests get run in a custom mattiasgeniar/php73 Docker container, which contains PHP 7.3 and extensions (including imagick).

With some fiddling you can easily adjust this to:

  1. Run these tests for pull requests too (just like you can automatically run linters on pull requests)
  2. Extend it to become a CI/CD pipeline to automatically deploy your code too

A github CI workflow tailored to modern PHP applications →

Run prettier or php-cs-fixer with GitHub Actions

Stefan Zweifel shares his GitHub Actions Workflows to run prettier and php-cs-fixer on his repos:

Over the past few weeks I’ve added a handful of workflows to my projects.

One workflow is really like, is to run prettier and php-cs-fixer to automatically format my code and commit the fixed files back to the repository.

Here’s the contents of the prettier workflow for example (.github/workflows/format_prettier):

name: Format (prettier)

on:
  pull_request:
    paths:
    - '**.css'
    - '**.js'
    - '**.vue'

jobs:
  prettier:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1

    - name: Install
      run: yarn install
      env:
        CI: true

    - name: Run prettier
      run: yarn run prettier --write 'src/**/*.{css,js,vue}'

    - uses: stefanzweifel/git-auto-commit-action@v2.1.0
      with:
        commit_message: Apply prettier changes
        branch: ${{ github.head_ref }}
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Upon each PR the workflow spins up an ubuntu machine which:

  1. Checks out the code
  2. Installs the dependencies (given that prettier is listed as a dev dependency in package.json)
  3. Runs the linter on certain files, with autofix enabled
  4. Commits all changes made by the linter

The php-cs-fixer works in a similar way.

Run prettier or php-cs-fixer with GitHub Actions →

🤩 There’s more cool things you can do with GitHub Actions. Automatically compressing (image) assets for example is a really neat workflow. You can even use GitHub Actions to schedule deploys of your site.

🤔 Looking to set up prettier and/or php-cs-fixer? Look no further.

Freek on Twitter

Scheduling Deploys with GitHub Actions

Leveraging GitHub Workflows’ Scheduled Events (read: cronjobs that run on GitHub) the folks at De Voorhoede let their static site automatically be rebuilt overnight. They do this because they have some external content, which doesn’t get committed into the repo, included on their site.

Static websites don’t update by themselves. In case of code changes (git push) and content changes (CMS publish event) a user triggers an update. But what if an external system (regularly) updates but can’t be configured to trigger an update? Enter cron jobs.

As their site is deployed onto Netlify, they let GitHub perform a curl request to Netlify’s Deploy Webhook, thus rebuilding and redeploying their site.

Their workflow file .github/workflows/nightly-build.yml is straightforward:

name: Scheduled build
on:
  schedule:
  - cron: '30 3 * * *'
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Trigger our build webhook on Netlify
      run: curl -s -X POST "https://api.netlify.com/build_hooks/${TOKEN}"
      env:
        TOKEN: ${{ secrets.NETLIFY_CRON_BUILD_HOOK }}

The required NETLIFY_CRON_BUILD_HOOK is stored a GitHub Secret into the repo

Scheduling Netlify deploys with GitHub Actions →

💁‍♂️ Here’s a writeup I’ve done on deploying a static site onto Netlify, in case you’re looking for info on how to get started with Netlify.

Automatically compress images to your Pull Requests with this GitHub Action

The folks at Calibre have release a GitHub Action named “Image Actions” and I must say, it looks amazing insane:

Image actions will automatically compress jpeg and png images in GitHub Pull Requests.

  • Compression is fast, efficient and lossless
  • Uses mozjpeg + libvips, the best image compression available
  • Runs in GitHub Actions, so it’s visible to everyone

Never ship unoptimised graphics again!

Once the workflow is added to your repo, Compression levels and source paths exclusions can easily be configured using a .github/calibre/image-actions.yml file:

jpeg:
  quality: 80
png:
  quality: 80
ignorePaths:
  - "node_modules/**"

Calibre Blog: Automatically compress images on Pull Requests →
GitHub Actions Marketplace: Image actions →

🤔 In case you’re wondering why you should compress your images be sure to read Addy Osmani’s free ebook “Essential Image Optimization”

Automatic GitHub Changelog Generator

If your code/project always uses Pull Requests to add/fix stuff in your code (e.g. no direct commits on master), then Changelog Generator will come in handy. It’s a CLI tool (written in PHP) that automatically fetches all closed PRs and Issues between the targetted and the previously tagged release.

Installation is possible using Composer:

$ composer require jwage/changelog-generator

Once installed, run it like so:

$ changelog-generator generate --user=jwage --repository=changelog-generator --milestone=0.0.7

The snippet above will check all closed PRs and Issues that landed in between the 0.0.7 release and the one before (e.g. 0.0.6) of the repo jwage/changelog-generator.

0.0.7
=====

- Total issues resolved: **1**
- Total pull requests resolved: **4**
- Total contributors: **3**

Improvement
-----------

 - [47: Upgrade Doctrine Coding Standards to 5.0](https://github.com/jwage/changelog-generator/pull/47) thanks to @jwage
 - [43: Generate alternative (Setext, without #) Markdown format for headers](https://github.com/jwage/changelog-generator/pull/43) thanks to @Majkl578
 - [38: Fix: Provide missing required php version in composer](https://github.com/jwage/changelog-generator/pull/38) thanks to @prisis
 - [32: Upgrade PHPStan to 0.10](https://github.com/jwage/changelog-generator/pull/32) thanks to @jwage

Adding the --prepend --file=CHANGELOG.md options, will automatically prepend its output to CHANGELOG.md.

💡 In case you don’t always want to type the arguments you could define it as a custom composer command/script into your own project, or use a config file which is also supported.

Generate a Markdown Changelog from a GitHub milestone. →

GitHub Toggle Chrome Extension – Quickly toggle between a GitHub Repo and its GitHub Pages by the click of a button.

Last week Christian Heilmann (codepo8) released a handy bookmarklet that lets on switch between the GitHub Pages URL of a repo hosted on GitHub and the repo contents itself. This afternoon I took the liberty of transforming it into a Chrome Extension, mainly as an exercise to myself.

The extension adds a small button which becomes active whenever you are visiting a *.github.com or *.github.io domain. Upon clicking the button you toggle between the two URLs.

To create this plugin I started out with the core of Christian’s script and decorated the required Chrome Extension stuff around it. A few notes on the latter though:

GitHub Toggle Chrome Extension on the Chrome Web Store →
GitHub Toggle Chrome Extension Source (GitHub) →

🙇‍♂️ Manipulating Chrome through a JavaScript API reminds me of controlling Photoshop using JavaScript which has excellent scripting capabilities … using its Scripting API you can create a script for Photoshop to cut up a large image into tiles for use with Google Maps or a script that allows one to export/import translations from a Photoshop file.