Проблема
Займаючись розробкою пакету, який використовується клієнтами на різних версіях продукту та PHP, зіткнувся з проблемою лімітів GitHub API під час функціонального тестування.
Для тестування змін у пул-реквестах використовується Jenkins з великою матрицею тестів. Кількість тестів, різні версії продукту плюс різні версії PHP - отримуємо дійсно велику матрицю функціональних тестів.
Після чергового додавання нової версії продукту в матрицю, тести почали падати у випадковому порядку з помилкою “Could not authenticate against github.com”.
Чому так відбувається?
Річ у тому, що я тягну пакет і деякі його залежності з GitHub.
Jenkins на одному з етапів генерує такий composer.json
, підставляючи потрібну версію продукту та PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
{
"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. Мій ліміт запитів до API становить 5000 за годину. Але, враховуючи кількість тестів, версій продукту та PHP, я почав вилазити за рамки цього ліміту.
Як перевірити GitHub API ліміти?
Щоб перевірити, скільки у тебе залишилося запитів до GitHub API, можна виконати наступну команду в терміналі:
1
|
curl -H "Accept: application/vnd.github+json" -H "Authorization: token <your-token>" https://api.github.com/rate_limit
|
<your-token>
потрібно замінити на твій GitHub токен, який ти використовуєш у auth.json
Приклад відповіді від GitHub:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
{
"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
}
}
|
Нас цікавить ось ця частина:
1
2
3
4
5
6
7
8
|
...
"rate": {
"limit": 5000,
"used": 5001,
"remaining": 0,
"reset": 1662134609
}
...
|
limit
- скільки всього дається запитів на годину
used
- скільки використано запитів
remaining
- скільки залишилося запитів
reset
- час, коли відбудеться скидання
У цьому прикладі можна побачити, що ліміт вичерпано.
Вирішення проблеми з GitHub API
Використання no-api
Один з варіантів - додавання опції no-api
до кожного composer.json
репозиторію на GitHub
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
{
"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
має наступний вигляд:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
{
"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
Якщо є ще якісь ідеї розв’язання цієї проблеми – пиши у коментарях.