Автор оригинала: Juan Sebastián Gaitán Villamizar.
Шаг за шагом. Нет API GitHub на Node.js.
Что мы строим?
Мы собираемся использовать силу yapfify для отслеживания комбиты в репозиторий GitHub, который у вас есть и/или работают для использования действия (пожалуйста, спросите вашего босса для разрешения, если требуется). Это может быть использовано для создания панели инструментов GitHUB для вашей компании, где каждый коммит отображается в реальном времени, как LiveTweetApp или Wall.io, хотя LiveGithubCommitApp. Вы считаете количество коммитов на разработчик. Количество строк изменяется. Все что пожелаете!
Это был бы отличный инструмент для хакатонов!
Как насчет API GitHub?
Следующий код для отслеживания GitHub требует минимальной настройки и не ограничивает вызовы API GitHub (что составляет 60 для неавторицированных и 5000 для вызовов аутентифицированных API, поэтому мы не используем его), и его можно использовать с кем-либо с доступом к репо Github.
Кроме того, мы получаем преданную строку в строке кода в консолидированном формате JSON, причем достаточно информации для его использования. Мы также выполняем код в Realtime, поскольку мы добавляем веб -ook каждому Push Commit, что репозиторий получает.
Плюсы:
- Минимальная установка
- Неограниченные звонки
- Консолидированный выход JSON
- Исполнение кода в реальном времени через веб-капли
- Имейте в виду, что это не заменит мощные API GitHub, это еще один способ автоматизировать задачу, с помощью Tiny Setup с помощью Attify – мощный инструмент для автоматизации веб-автоматизации.
Что такое отвратительное?
Atifify – это веб-сканер на облаке, который извлекает структурированные данные с любого веб-сайта, используя несколько простых строк JavaScript. Это веб-платформа Scraping и автоматизации. Он может превратить любой веб-сайт в API через несколько минут! Первое, что вы встретите на сайте, это гусеничный. Славатели размещены на yapfify для разработчиков. Каждый гусеник устанавливается, чтобы сделать определенную задачу соскабливания и автоматизации. Он смотрит на страницу и возвращает определенную информацию с этой страницы. Каждый гусеничный, технически, веб-браузер, размещенный на серверах apifify, которые позволяют просматривать данные с любого сайта, используя JavaScript. Гусеньер нуждается в двух вещах: URL для выполнения, и код JavaScript, который будет выполнен.
Что такое акт?
Закон является единой производительностью актера. Actor – это компьютерная платформа, которая позволяет выполнять произвольные кусочки кода в облачном облаке yapfify. Это означает, что вы можете запустить работу, такую как заполнение формы или отправки почты или даже ползания всей страницы. Одно изолированное задание актера называется ACT, он имеет настройки и исходный код. В отличие от традиционных платформ без сервеса, акт не ограничивается сроком службы одной транзакции HTTP. Это может работать так долго, как это необходимо, даже навсегда. ACT – это одно облачное приложение или обслуживание.
Начиная
На левой панели вы можете пойти в актер и начать создавать действие.
Вы можете использовать API, установить библиотеку или разместить его онлайн. Вы столкнетесь с несколькими вкладками, когда вы решите создать новые.
Перейдите на вкладку «Источник» и добавьте следующий код:
const Apify = require('apify'); const request = require('request-promise'); Apify.main(async () => { // Get input of your act const input = await Apify.getValue('INPUT'); console.log('My input:'); console.dir(input); // Do something useful here const html = await request('http://www.example.com'); // And then save output const output = { html, crawledAt: new Date(), }; console.log('My output:'); console.dir(output); await Apify.setValue('OUTPUT', output); });
Это базовый код, чтобы начать. Нажмите кнопку «Быстрый запуск», и она будет строить и запустить ваш вновь созданный акт. Попробуйте!
Ваш акт идет и работает!
Для сложных действий удобнее хостить исходный код на Git. Вы можете клонировать код Boeterplate из Быстрый запуск Репозиторий, чтобы начать. Мы сделаем это для нашего Github Tracker.
Когда вы находитесь на вкладке «Источник», выберите «Исходный тип» в виде хранилища GIT.
Введите URL на ваш репозиторий Git, и вы приятно построить. В нашем случае мы бы использовали этот репозиторий: https://github.com/juansgaitan/act-git-tracker Отказ
Если это удастся, вы получите статус как успешно:
На GitHub, чтобы отслеживать любые у вас храбрость, перейдите к Настройки> веб-кауки а потом Добавить веб -ook Отказ
«URL-адрес полезной нагрузки» будет URL-адресом «act Run», который можно найти на вкладке «API» на платформе Adify.
Теперь просто опубликуйте приложение и запустите с вкладки актера. Теперь, каждый раз, когда вы подталкиваете фиксирую на ваш REPO GitHUB, он сохранит фиксацию в файле JSON, который можно использовать для обслуживания приложения Frontend (как упоминалось ранее) или выполнять другие полезные вещи.
Код
Давайте сломаем код вниз по шагам:
- Начните, требуя пакета Aquify, Cheerio и Project-Promise. Это единственные пакеты, которые мы будем использовать для этого приложения – все пакеты NPM поддерживаются. (Линии 1 – 3)
- Дополнительные функции утилиты для упрощения читаемости. (Линии 6 – 7)
- Начните выполнение, вызывая Atifify.main (), эта функция не является обязательной. (Линия 20)
- Передайте async-функцию к основной функции, чтобы воспользоваться ключевым словом await для обработки асинхронных казней. (Линии 20 – конец)
- Apthify.getValue () приносит ввод, который мы передаем в наш код для выполнения. Акт может работать без этого ввода, хотя рекомендуется, поскольку он передает ему внешние параметры, создавая гибкость и емкость для расширения его функциональности для большего количества использования случаев. В этом случае вход является полезной нагрузкой через GitHub WebHook. (Линия 22 – 23) Линии 28 по 38, объяснены в своем собственном разделе ниже. Магазин ключа-значений.
«Магия здесь»
- На линии 56 – 87, «Магия здесь», – это то, где мы запрашиваемprise Blob URL нашего коммита и извлечь всю необходимую информацию. Поскольку мы не используем API GitHub, мы запрашиваем каждому Code Blob и inject Cheerio для обработки содержимого HTML страницы. Затем мы уменьшаем код в StateChanges и присваиваем его новому объекту, с нашей предыдущей.
const Apify = require('apify'); const cheerio = require('cheerio'); const requestPromise = require('request-promise'); // Utils functions to simplify the code const { log } = console; const pretty = object => JSON.stringify(object, null, 2); // Get code line-by-line with cheerio into an Object const arrayToObjectInContext = $ => (array, object = {}) => ( array.reduce((acc, tr) => { const $tr = $(tr); const lineNumber = $tr.find('[data-line-number]').data('line-number'); const code = $tr.find('.blob-code-inner').text(); return Object.assign({}, acc, { [lineNumber]: code }); }, object) ); // Apify's main function to encapsule execution - optional Apify.main(async () => { // payload from the WebHook const payload = await Apify.getValue('INPUT'); const { repository, head_commit: headCommit } = payload; const { id: repositoryId } = repository; log('Repository ID:', repositoryId); // Create a repoStore to handle 'STATE' for each repo const repoStore = await Apify.openKeyValueStore(`Repository-${repositoryId}`); // Getting record 'STATE', if any let previousState = {}; try { previousState = await repoStore.getValue('STATE'); } catch (err) { // ignore this error } log('Previous STATE:', pretty(previousState)); // Get Commit SHA, 7 characters are enough const commitId = headCommit.id.slice(0, 7); log('Current Commit ID:', commitId); const { added, removed, modified } = headCommit; const headCommitFiles = [].concat(added, removed, modified); log('Added/Removed/Modified Files:', headCommitFiles); // Add blob URL to each file const commitBlobUrl = headCommit.url.replace('commit', 'blob'); const commitBlobUrls = headCommitFiles.map(file => ({ uri: `${commitBlobUrl}/${file}`, file: file.toLowerCase(), })); // Magic here const stateChanges = await commitBlobUrls.reduce(async (acc, { uri, file }) => { log('Blob URL:', uri); const options = { uri, transform: body => cheerio.load(body), }; const $ = await requestPromise(options); const getDiffIn = arrayToObjectInContext($); const $tableRows = $('table tr').toArray(); log(`Lines found in '${file}': ${$tableRows.length}`); const fileState = previousState[file] || []; const currentState = fileState.filter(commitObject => !commitObject[commitId]); const commit = { [commitId]: { timestamp: headCommit.timestamp, committer: headCommit.committer, message: headCommit.message, url: headCommit.url, }, }; // Filtering non .js files if (file.includes('.js')) { Object.assign(commit[commitId], { code: getDiffIn($tableRows) }); } return Object.assign({}, acc, { [file]: [commit, ...currentState] }); }, {}); const nextState = Object.assign({}, previousState, stateChanges); log('Next STATE:', pretty(nextState)); log('Saving into repoStore:', repositoryId); await repoStore.setValue('STATE', nextState); // Save 'OUTPUT' of the current Act run // (optional - necessary only if called from within an act to get its 'OUTPUT') await Apify.setValue('OUTPUT', nextState); return log('Done.'); });
Магазины ключей
Каждый класс Aquify поставляется с несколькими Методы , в том числе интегрированный экземпляр в пакет ApifyClient (APIFIFY.ciclient). Мы будем использовать OpenKeyValuestore Метод открыть магазин для каждого из наших репо.
const repoStore = await Apify.openKeyValueStore( `Repository-${repositoryId}` );
StoreName (Репозиторий – $ {ReposityId}) Параметр, который мы используем, должно быть одинаковое имя магазина каждый раз, когда мы называем OpenKeyValuestore, так как мы хотим добавить новый коммит по одному репостору.
// Getting record 'STATE', if any let previousState = {}; try { previousState = await repoStore.getValue('STATE'); } catch (err) { // ignore this error }
Состояние наших коммитов вкладывается в одинаковую запись под «государственным» именем. Итак, мы называем GetValue Метод включен в репостор, который мы создали. Для целей обработки ошибок мы обертываем отклик вокруг попытки/улова, и если этот ответ имеет тело, мы назначаем его предыдущей переменной. На этот раз мы игнорируем какие-либо ошибки.
Теперь мы готовы обрабатывать данные, как мы хотим. Тогда, чтобы SetValue Вернуться в магазин, мы передаем имя записи, «состояние» и NextState в качестве второго параметра.
await repoStore.setValue('STATE', nextState);
Это оно?
Да! Мы создали полноценную API, которое возвращает файл JSON каждый раз, когда в репозитории получается фиксатор. Мы храним данные на вкладке «Хранение» под названием «Репозиторий-репозиторий-ID-ID – здесь» внутри ключа состояния (если у вас нет ничего там, это потому, что вы еще не подталкивались – это не ретроактивно !).
ВЫХОД
Проверьте это здесь Отказ
Это первый пост серии для создания полноценных API с Appify Отказ Не забудьте Подписаться быть уведомленным для следующего поста.