Проблема
Занимаясь разработкой пакета, который используется клиентами на разных версиях продукта и php, столкнулся с проблемой лимитов GitHub API при функциональном тестировании.
Для тестирования изменений в пул-реквестах используется Jenkins с большой матрицей тестов. Количество тестов, разные версии продукта, плюс разные версии php - получаем действительно большую матрицу функциональных тестов.
После очередного добавления новой версии продукта в матрицу тесты начали падать случайным образом с ошибкой “Could not authenticate against github.com”.
Почему так происходит?
Все дело в том, что я тяну тестируемый пакет и пару его зависимостей с GitHub.
Jenkins на одном из этапов генерирует такой composer.json, подставляя нужную версию продукта и php:
{
"name": "vendor/tested-package",
"description": "The example",
"version": "1.2.3",
"repositories": {
"tested-package-repo": {
"type": "vcs",
"url": "https://github.com/vendor/tested-package.git"
},
"dependency-1": {
"type": "vcs",
"url": "https://github.com/vendor/dependency-1.git"
},
"dependency-2": {
"type": "vcs",
"url": "https://github.com/vendor/dependency-2.git"
},
"dependency-3": {
"type": "vcs",
"url": "https://github.com/vendor/dependency-3.git"
},
"composer-repo.vendor.org": {
"type": "composer",
"url": "composer-repo.vendor.org"
}
},
"require": {
"php": "7.2",
"vendor/product": "1.10.22",
"vendor/tested-package": "dev-develop as 1.2.3",
"vendor/dependency-1": "dev-develop as 2.0.1",
"vendor/dependency-2": "dev-develop as 2.0.2",
"vendor/dependency-3": "dev-develop as 2.0.3"
}
}
На следующем этапе Jenkins выполняет composer update
, а затем запускает функциональный тест.
Composer для получения информации с репозиториев использует GitHub API. Мой лимит 5000 запросов к API в час. Но учитывая количество тестов, версий продукта и php - я начал вылезать за рамки этого лимита.
Как проверить GitHub API лимиты?
Чтобы проверить сколько у тебя осталось запросов к GitHub API можно выполнить следующую команду в терминале:
curl -H "Accept: application/vnd.github+json" -H "Authorization: token <your-token>" https://api.github.com/rate_limit
<your-token>
нужно заменить на твой GitHub токен, который ты используешь в auth.json
Пример ответа от GitHub:
{
"resources": {
"core": {
"limit": 5000,
"used": 5001,
"remaining": 0,
"reset": 1662134609
},
"search": {
"limit": 30,
"used": 0,
"remaining": 30,
"reset": 1662133328
},
"graphql": {
"limit": 5000,
"used": 0,
"remaining": 5000,
"reset": 1662136868
},
"integration_manifest": {
"limit": 5000,
"used": 0,
"remaining": 5000,
"reset": 1662136868
},
"source_import": {
"limit": 100,
"used": 0,
"remaining": 100,
"reset": 1662133328
},
"code_scanning_upload": {
"limit": 1000,
"used": 0,
"remaining": 1000,
"reset": 1662136868
},
"actions_runner_registration": {
"limit": 10000,
"used": 0,
"remaining": 10000,
"reset": 1662136868
},
"scim": {
"limit": 15000,
"used": 0,
"remaining": 15000,
"reset": 1662136868
},
"dependency_snapshots": {
"limit": 100,
"used": 0,
"remaining": 100,
"reset": 1662133328
}
},
"rate": {
"limit": 5000,
"used": 5001,
"remaining": 0,
"reset": 1662134609
}
}
Нас интересует вот эта часть:
...
"rate": {
"limit": 5000,
"used": 5001,
"remaining": 0,
"reset": 1662134609
}
...
limit
- сколько всего дается запросов в часused
- сколько использовано запросовremaining
- сколько осталось запросовreset
- время когда произойдет сброс
В этом примере можно увидеть, что лимит исчерпан.
Решение проблемы с GitHub API
Использование no-api
Один из вариантов - добавление опции no-api
к каждому GitHub репозиторию в composer.json:
{
"name": "vendor/tested-package",
"description": "The example",
"version": "1.2.3",
"repositories": {
"tested-package-repo": {
"type": "vcs",
"url": "https://github.com/vendor/tested-package.git",
"no-api": true
},
"dependency-1": {
"type": "vcs",
"url": "https://github.com/vendor/dependency-1.git",
"no-api": true
},
"dependency-2": {
"type": "vcs",
"url": "https://github.com/vendor/dependency-2.git",
"no-api": true
},
"dependency-3": {
"type": "vcs",
"url": "https://github.com/vendor/dependency-3.git",
"no-api": true
},
"composer-repo.vendor.org": {
"type": "composer",
"url": "composer-repo.vendor.org"
}
},
"require": {
"php": "7.2",
"vendor/product": "1.10.22",
"vendor/tested-package": "dev-develop as 1.2.3",
"vendor/dependency-1": "dev-develop as 2.0.1",
"vendor/dependency-2": "dev-develop as 2.0.2",
"vendor/dependency-3": "dev-develop as 2.0.3"
}
}
Используя эту опцию composer не использует GitHub API для получения информации с репозитория, вместо этого он клонирует репозиторий и считавает нужную иформацию с локально репозитория.
Этот подход решает проблему с API лимитами, но выполнение тестов может занять в 2-3 раза больше времени, так как клонирование более медленное чем использование API.
Использование собственного composer репозитория
Можно поднять на машине с Jenkins свой composer репозиторий и использовать его для хранения тестируемых пакетов и их зависимостей.
Что я и сделал.
Перед этапом генерации composer.json я добавил еще один этап - упаковка и публикация тестируемого пакета и его зависимостей в свой composer репозиторий.
После этих изменений composer.json имеет следующий вид:
{
"name": "vendor/tested-package",
"description": "The example",
"version": "1.2.3",
"repositories": {
"test-repo": {
"type": "composer",
"url": "127.0.0.1"
}
"composer-repo.vendor.org": {
"type": "composer",
"url": "composer-repo.vendor.org"
}
},
"require": {
"php": "7.2",
"vendor/product": "1.10.22",
"vendor/tested-package": "1.2.3",
"vendor/dependency-1": "2.0.1",
"vendor/dependency-2": "2.0.2",
"vendor/dependency-3": "2.0.3"
}
}
Проблема с GitHub API лимитами была решена без ущерба скорости выполнения тестов.
Для поднятия собственного composer репозитория ты можешь использовать, например, Satis
Если есть ещё какие-то идеи решения этой проблемы - пиши в комментариях.