8. Fork composer package. Gitlab, github, local. Як редагувати пакети composer

Відео версія
(YouTube - для зворотнього зв'язку)

Ситуації, коли для розробки необхідно редагувати якусь залежність composer, виникають часто. Це може бути банальна зміна версії PHP у вимогах, до якої ще не добрався maintainer пакету. Або ж унікальні зміни, що через різні причини не вносяться в пакет. Сюди входять і пакети, підтримка яких припинилася або ж перебуває у невизначеному стані.

GitHub Fork

Абсолютна більшість composer пакетів розміщують вихідний код на GitHub. І саме з GitHub найлегше зробити копію репозиторію для ваших потреб. Це буквально одне натискання кнопки "fork". Простенька форма, і ви маєте власну копію бібліотеки.

Тут лише одна порада - не редагуйте основну гілку вашого форку. GitHub дає змогу дуже легко синхронізувати оригінал з вашим форком, що не так легко зробити, коли ви маєте конфлікти в гілці main або master.

Тож дуже простий алгоритм: робимо fork, створюємо свою гілку, редагуємо. І в composer додаємо репозиторій repositories з посиланням на fork:

composer.json
{
  "repositories": {
    "github": {
      "type": "vcs",
      "url": "https://github.com/your-github-name/fork-package"
    }
  }
}

І оновлюємо пакет з версією у форматі dev-branchname.

Префікс dev- - обов'язковий, branchname - назва гілки:

cli
composer req package/name:dev-branchname

GitLab Fork

GitLab підтримує повне клонування репозиторіїв з GitHub (та інших). Тут важливо розуміти, що цей функціонал більше не про fork, а про перенесення проєктів. Але якщо ваш проєкт саме в GitLab, то є сенс зберігати всі third-party бібліотеки саме там.

При створенні проєкту (обов'язково в групі або підгрупі, бажано в якій буде використовуватись пакет) оберіть Import project => Repository by URL. Якщо ви Premium користувач, оберіть Mirror repository - і будете автоматично отримувати оновлення (що правда, всіх гілок). Будьте готові, що GitLab витягне всі гілки та теги.

Рекомендація така ж, як і в GitHub: не редагуйте основну гілку.

Перед тим, як використовувати код як composer пакет, його треба помістити в Package registry.

.gitlab-ci.yml
stages:
  - deploy

deploy_composer:
  image: alpine:3.20.0
  stage: deploy
  before_script:
    - apk add curl
  script:
    - 'curl --header "Job-Token: ${CI_JOB_TOKEN}" --data tag=$CI_COMMIT_TAG "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/composer"'
  rules:
    - if: '$CI_COMMIT_TAG =~ /^(\d+\.)?(\d+\.)?(\*|\d+)-dev$/'

Цей скрипт запуститься для всіх тегів у форматі семантична версія + -dev. Суфікс -dev - не обов'язковий, але раджу додавати, щоб не конфліктувати з тегами оригіналу.

Deploy => Package registry покаже список доступних пакетів.

Важливо розуміти, що доступ до сховища пакетів реалізований через групу, без групи він не працює. Саме в групі можна зайти на Deploy => Package registry до конкретного проєкту й отримати команду для автоматичного налаштування в композері:

cli
composer config repositories.gitlab.com/pakage_group_id '{"type": "composer", "url": "https://gitlab.com/api/v4/group/PACKAGE_GROUP_ID/-/packages/composer/packages.json"}'

Це створить репозиторій, який можна додати в ручну

composer.json
{
  "repositories": {
    "gitlab.com": {
      "type": "composer",
      "url": "https://gitlab.com/api/v4/group/pakage_group_id/-/packages/composer/packages.json"
    }
  }
}

Це надасть доступ до всіх пакетів у групі:

cli
composer req package/name:tagname

Доступ до пакетів закритий за замовчуванням. Два варіанти роботи:

  1. Дозволити всім доступ на зчитування: Settings => General => Visibility, project features, permissions => Package registry => Allow anyone to pull from Package Registry.
  2. Авторизуватися. Для локальної роботи - авторизуватися за допомогою ім'я користувача та токену з доступом read_api. Використати команду:
cli
composer config gitlab-token.gitlab.com token __token__

Це створить файл auth.json - прослідкуйте, щоб він був у .gitignore.

Для закритого проєкту CI/CD обов'язково: Settings => CI/CD => Token Access => Limit access to this project. Add group or project додаємо назву проєкту або групи (підгрупи), що використовує пакет. І додаємо авторизацію як крок перед інсталяцією залежностей:

.gitlab-ci.yml
before_script:
  - docker-compose exec app composer config -- gitlab-token.gitlab.com gitlab-ci-token "${CI_JOB_TOKEN}"

Локально (Docker)

Для тестування роботи пакета локально пропишіть репозиторій:

composer.json
{
  "repositories": {
    "local": {
      "type": "path",
      "url": "/absolute/path_to_package_directory"
    }
  }
}

Та оновіть командою:

cli
composer req package/name:@dev

@dev - обов'язкова, підказує composer створити посилання на директорію з локальним пакетом.

Якщо працюєте в Docker для локальної роботи, посилання з хоста до контейнера не створиться. Тож має сенс створити volume і в repositories.local.url прописати шлях до директорії в контейнері. Не забувайте створювати директорію в контейнері вручну, volume не створює директорій у контейнері. Приклад для Docker Compose:

cli
docker compose exec mkdir some_dir

.gitlab-ci.yml
your_service:
  volume:
    - /absolute/path_to_package_directory:/some_dir

composer.json
{
  "repositories": {
    "local": {
      "type": "path",
      "url": "/some_dir"
    }
  }
}

Все це не йде в гіт! Лише для локальної роботи.