An overlay script for composer, providing support for composer.yaml files.
- Purpose
- Requirements
- Install
- How it works
- Usage
- Compatibility caveats
- About the project's name
- Credits
- License
This project was initiated to address the lack of support for YAML format in composer.
Indeed, YAML has several advantages over JSON:
-
It supports comments, natively.
In the meantime developers must use awful hacks to insert comments in theirJSONcontents, like creating fake_commentproperties... -
It's human-readable.
Ever struggled with a merge conflict on acomposer.lockfile? Tough huh?
A concrete example: the yamltools lock file.
#
# This file was generated automatically by Offenbach
# @see https://github.com/yannoff/offenbach for details
#
_readme:
- 'This file locks the dependencies of your project to a known state'
- 'Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies'
- 'This file is @generated automatically'
content-hash: bbb0e45340feb244228603615130c04f
packages:
-
name: symfony/polyfill-ctype
version: v1.19.0
source:
type: git
url: 'https://github.com/symfony/polyfill-ctype.git'
reference: aed596913b70fae57be53d86faa2e9ef85a2297b
dist:
type: zip
url: 'https://api.github.com/repos/symfony/polyfill-ctype/zipball/aed596913b70fae57be53d86faa2e9ef85a2297b'
reference: aed596913b70fae57be53d86faa2e9ef85a2297b
shasum: ''
require:
php: '>=5.3.3'
suggest:
ext-ctype: 'For best performance'
type: library
extra:
branch-alias:
dev-main: 1.19-dev
thanks:
name: symfony/polyfill
url: 'https://github.com/symfony/polyfill'
autoload:
psr-4:
Symfony\Polyfill\Ctype\: ''
files:
- bootstrap.php
notification-url: 'https://packagist.org/downloads/'
license:
- MIT
authors:
-
name: 'Gert de Pagter'
email: BackEndTea@gmail.com
-
name: 'Symfony Community'
homepage: 'https://symfony.com/contributors'
description: 'Symfony polyfill for ctype functions'
homepage: 'https://symfony.com'
keywords:
- compatibility
- ctype
- polyfill
- portable
support:
source: 'https://github.com/symfony/polyfill-ctype/tree/v1.19.0'
funding:
-
url: 'https://symfony.com/sponsor'
type: custom
-
url: 'https://github.com/fabpot'
type: github
-
url: 'https://tidelift.com/funding/github/packagist/symfony/symfony'
type: tidelift
time: '2020-10-23T09:01:57+00:00'
-
name: symfony/yaml
version: v3.4.47
source:
type: git
url: 'https://github.com/symfony/yaml.git'
reference: 88289caa3c166321883f67fe5130188ebbb47094
dist:
type: zip
url: 'https://api.github.com/repos/symfony/yaml/zipball/88289caa3c166321883f67fe5130188ebbb47094'
reference: 88289caa3c166321883f67fe5130188ebbb47094
shasum: ''
require:
php: ^5.5.9|>=7.0.8
symfony/polyfill-ctype: ~1.8
conflict:
symfony/console: '<3.4'
require-dev:
symfony/console: ~3.4|~4.0
suggest:
symfony/console: 'For validating YAML files using the lint command'
type: library
autoload:
psr-4:
Symfony\Component\Yaml\: ''
exclude-from-classmap:
- /Tests/
notification-url: 'https://packagist.org/downloads/'
license:
- MIT
authors:
-
name: 'Fabien Potencier'
email: fabien@symfony.com
-
name: 'Symfony Community'
homepage: 'https://symfony.com/contributors'
description: 'Symfony Yaml Component'
homepage: 'https://symfony.com'
support:
source: 'https://github.com/symfony/yaml/tree/v3.4.47'
funding:
-
url: 'https://symfony.com/sponsor'
type: custom
-
url: 'https://github.com/fabpot'
type: github
-
url: 'https://tidelift.com/funding/github/packagist/symfony/symfony'
type: tidelift
time: '2020-10-24T10:57:07+00:00'
-
name: yannoff/console
version: 1.3.1
source:
type: git
url: 'https://github.com/yannoff/console.git'
reference: a81ecb24f9466684636eea4133e7c7959979220f
dist:
type: zip
url: 'https://api.github.com/repos/yannoff/console/zipball/a81ecb24f9466684636eea4133e7c7959979220f'
reference: a81ecb24f9466684636eea4133e7c7959979220f
shasum: ''
type: library
autoload:
psr-4:
Yannoff\Component\Console\: src/
notification-url: 'https://packagist.org/downloads/'
license:
- MIT
authors:
-
name: Yannoff
homepage: 'https://github.com/yannoff'
description: 'A simple, lightweight console implementation for command-line PHP applications.'
homepage: 'https://github.com/yannoff/console'
support:
issues: 'https://github.com/yannoff/console/issues'
source: 'https://github.com/yannoff/console/tree/1.3.1'
time: '2022-02-22T18:59:49+00:00'
-
name: yannoff/y-a-m-l
version: 1.1.5
source:
type: git
url: 'https://github.com/yannoff/y-a-m-l.git'
reference: 78d0dd8e0f81056ba3ed04ac6b825c3464e8fcae
dist:
type: zip
url: 'https://api.github.com/repos/yannoff/y-a-m-l/zipball/78d0dd8e0f81056ba3ed04ac6b825c3464e8fcae'
reference: 78d0dd8e0f81056ba3ed04ac6b825c3464e8fcae
shasum: ''
require:
ext-json: '*'
require-dev:
squizlabs/php_codesniffer: ^3.4
type: php-library
autoload:
psr-4:
Yannoff\Component\YAML\: src
notification-url: 'https://packagist.org/downloads/'
license:
- MIT
authors:
-
name: Yannoff
homepage: 'https://github.com/yannoff'
description: 'Y.A.M.L : Yaml Abstraction Model Layer'
homepage: 'https://github.com/yannoff/y-a-m-l'
support:
issues: 'https://github.com/yannoff/y-a-m-l/issues'
source: 'https://github.com/yannoff/y-a-m-l/tree/1.1.5'
time: '2021-09-12T13:59:09+00:00'
packages-dev: []
aliases: []
minimum-stability: stable
stability-flags: []
prefer-stable: false
prefer-lowest: false
platform:
php: '>=5.6.40'
ext-json: '*'
platform-dev: []
plugin-api-version: 2.2.0(1) Should also work on Git Bash / MinTTY, although it has not been tested hitherto.
(2) Will be downloaded at build time by the install script if not found on the system.
The script can be executed on-the-fly, from the target install directory:
curl -L -s -o - https://github.com/yannoff/offenbach/releases/latest/download/install.sh | bashSee the examples section for customized installation examples.
The online installer script supports a few configuration options allowing for a more fine-tuned installation.
| Option | Default | Description | Env var |
|---|---|---|---|
--install-dir |
$PWD (ie: current directory) |
Offenbach installation directory (3) (4) | OFFENBACH_INSTALL_DIR |
--filename |
offenbach |
Name of the installed executable | OFFENBACH_FILENAME |
--version |
latest |
Alternative version to install | OFFENBACH_VERSION |
(3) For
offenbachto be accessible globally, the install dir must be in the$PATHsystem-wide variable.
(4) The script may be invoked insudomode if the install dir is not owned by the standard user.
curl -SL -o /tmp/install.sh https://github.com/yannoff/offenbach/releases/latest/download/install.sh
sudo /tmp/install.sh --install-dir=/usr/local/bin --filename=offenbachurl=https://github.com/yannoff/offenbach/releases/latest/download/install.sh
curl -SL -s -o - ${url} | env OFFENBACH_INSTALL_DIR=$HOME/bin OFFENBACH_VERSION=1.6.1 bash# Fetch the sources from the repository
git clone https://github.com/yannoff/offenbach
# Enter the project's directory
cd offenbach
# Configure installation (5)
./configure bin/offenbach
# Build
make
# Install executable (6)
sudo make install(5) The
--helpoption will give a thorough overview of the possible customizations.
(6) Depending on the install directory set up,sudomight not be used.
A github action version of the installer is also available for integration in CI scripts.
The action will install PHP, composer & offenbach.
Synopsis: use yannoff/offenbach/actions/install@<release>.
Installing offenbach version 1.7.1 / PHP 8.0
# ...
jobs:
mycijob1:
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install PHP & Offenbach
uses: yannoff/offenbach/actions/install@1.7.1
with:
php-version: 8.0
- name: Install dependencies (Offenbach)
run: offenbach installA concrete working use case can be found in the phpcc project.
Offenbach works exactly as composer, indeed it is just an overlay script, acting as a pass-thru for composer commands.
The key principle is really simple: Offenbach will create 2 temporary JSON files before each operation, feed composer with them, then convert them back to YAML format.
From the user's perspective, the only difference is in the composer files:
- The
composer.jsonfile is replaced by acomposer.yamlfile - The
composer.lockfile is replaced by acomposer-lock.yamlfile
However, a few limitations must be considered.
offenbachonly handles project composer files (7)- projects using
offenbachinstead ofcomposerwill not be eligible for publication on packagist. - only
*.jsonand*.yamlfilenames are allowed for theCOMPOSERenv var.
(7) The global composer files in
COMPOSER_HOMEare left in their original standard JSON format.
There are 2 major use cases:
⚠️ Before proceeding, be sure you have read the compatibility notice.
As for a composer project, run:
offenbach initAfter prompting for the usual few questions, offenbach will create the 2 composer files:
composer.yaml(standing for thecomposer.jsonfile)composer-lock.yaml(standing for thecomposer.lockfile)
⚠️ BEWARE
Migrating from composer to offenbach is a one-way operation, there is no possible return to use composer back after the project has been migrated.
In a shell terminal, from the project root (i.e. the directory where the composer.json reside), run:
offenbach migrate💡 Alternatively, any call to standard composer commands, such as:
offenbach installoffenbach update --lockwill trigger a migration.
As a result, offenbach will use the initial composer.json and composer.lock files to build their YAML counterparts (composer.yaml and composer-lock.yaml, respectively), then remove them.
Since packagist analysis is based on the project metadata deduced from the composer.json file contents,
it will fail to recognize offenbach's composer.yaml file.
As a consequence, projects using offenbach will not be able to publish on packagist.org.
PSR-0 / PSR-4 automatic detection may not work properly on PhpStorm, as it is based on the composer.json file contents.
Since by default the symfony Kernel::getProjectDir() method uses the composer.json location to find out the project's root directory, it's necessary to override the method.
For instance:
<?php
// src/Kernel.php
namespace App;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
class Kernel extends BaseKernel
{
use MicroKernelTrait;
// ...
/**
* Don't use composer.json to find the project root
*
* @return string
*/
public function getProjectDir()
{
return dirname(__DIR__);
}
// ...
}The Application::getNamespace() method (used by some artisan make:* commands to populate PHP code auto-generated from stubs) relies on the composer.json contents to find out the application's PSR-4 namespace, and hence must be overriden in a custom Application class.
⚠️ BEWARE
Thesymfony/yamlcomponent must be part of the dependencies list.
Be sure to add it before implementing the customApplicationclass override:offenbach require symfony/yaml
For instance:
<?php
// app/Foundation/Application.php
namespace App\Foundation;
// Don't forget to import the Yaml class
use Symfony\Component\Yaml\Yaml;
class Application extends \Illuminate\Foundation\Application
{
/**
* Override base method to support offenbach
*
* @return string
*
* @throws \RuntimeException
*/
public function getNamespace()
{
// ...
// Original code
//$composer = json_decode(file_get_contents($this->basePath('composer.json')), true);
// Replacement: Add support for composer.yaml beside standard composer.json files
if (file_exists($this->basePath('composer.yaml'))) {
$composer = Yaml::parseFile($this->basePath('composer.yaml'));
} else {
$composer = json_decode(file_get_contents($this->basePath('composer.json')), true);
}
// ...
}Then use the custom class:
// bootstrap/app.php
$app = App\Foundation\Application(
$_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);Jacques Offenbach (1819-1880) was a German-born French composer of the 19th.
The concepts behind offenbach were highly inspired by the igorw/composer-yaml project.
Licensed under the MIT License.