Featured image of post Функціональні тести та ліміти API GitHub

Функціональні тести та ліміти API GitHub

Під час функціонального тестування виникає помилка: Could not authenticate against github.com

Проблема

Займаючись розробкою пакету, який використовується клієнтами на різних версіях продукту та 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

Якщо є ще якісь ідеї розв’язання цієї проблеми – пиши у коментарях.

comments powered by Disqus
Створено з Hugo
Тема Stack, дизайн Jimmy