Я начал использовать действия GitHub A, одновременно обратно для обработки рабочих процессов в некоторых проектах, в основном для создания изображений докеров или запущенных тестов. Их легко настроить, и MarketPlace Github имеет большое количество из них в различных целях, от управляющих тестов и трубопроводов развертывания, чтобы добавить кошек MEMES к вашему PRS.
Я хотел бы некоторое время посмотреть под капюшоном и посмотреть, как я могу создать свои собственные пользовательские действия и, наконец, последние выходные мне удалось пройти свою документацию и посмотреть на некоторые образцы и поставить что-то вместе. Это сводка моего первого действия GitHub.
Вы можете найти окончательное действие здесь или на Github Marketplace Отказ
Согласно Документы , есть 3 вида действий: Докер (использует контейнеры докеров, чтобы запустить операции действий в), JS (Действия, написанные в JS/TS), а Композитные шаги (может иметь несколько шагов).
У меня была простая идея для моего первого действия:
Мне нужно было что-то, чтобы заблокировать изменения (слиться и толчок) в данные ветви в течение периодов времени, указанных в качестве входов.
Действия JS звучали как хороший и простой способ сделать это.
Я начал с создания репо Действия/Типоприпечатка-действие шаблон. Этот шаблон содержит действие, которое ждет на несколько миллисекунд (переданных в качестве ввода) и передает время окончания его прогона в качестве вывода. Если что-то пойдет не так, он бросает ошибку и останавливает рабочий процесс.
Я прошел через файлы, чтобы увидеть, что мне нужно было изменить для моего собственного действия. Вот список основных изменений:
package.json
(Конечно!): Обновлена атрибуты и зависимости.Action.yml
: Определение действия, включая его входы и выходы, идет здесь.SRC/**
: Основная логика действия идет здесь.__tests__
: Только если вам нужно проверить свой код!
Основная зависимость для действия JS является @ Действия/ядро . Он предоставляет функции, которые включают основные взаимодействия через рабочий процесс: например. Получение входов, настройки выходов и регистрации.
Есть и другие пакеты JS, предоставленные Github для использования в ваших действиях, хотя мне не нужно ни одного из них для моей цели. Вы можете увидеть список здесь Отказ
Мои изменения в package.json
были тривиальными, поэтому я их пропускаю.
Следующий шаг обновил Action.yml
и регулировка входов и выходов. Вот содержимое обновленного файла:
name: 'No Weekend Merge' description: 'An action to prevent merges on weekends, or whenever that a merge should not happen' author: 'ka7eh' branding: icon: git-merge color: green inputs: tz: required: true description: 'Timezone of the downtime periods' default: '0' mon: required: false description: 'When to block on Mondays' tue: required: false description: 'When to block on Tuesday' wed: required: false description: 'When to block on Wednesday' thu: required: false description: 'When to block on Thursday' fri: required: false description: 'When to block on Friday' sat: required: false description: 'When to block on Saturday' sun: required: false description: 'When to block on Sunday' runs: using: 'node12' main: 'dist/index.js'
Первые 3 атрибута очевидны (имя, описание и автор).
Брендинг не является обязательным. Это позволяет создать знак для вашего действия. Вы можете выбрать имя значка из Перо и установить его цвет.
В бежит
Раздел Action.yml
Я указываю узел 12 как мой бегун действий. Я также указываю на окончательную сборку кода, который идет в Dist
(сборка обрабатывается TSC
и @ vercel/ncc
; Проверьте построить
и Пакет
Сценарии в package.json
). Используя пакет, который включает в себя все необходимые зависимости, должны уменьшить сложность и источники ошибок при запуске действия в рабочем процессе.
Примечание: в настоящее время только узел 12 поддерживается для действий JS.
Мое действие не предоставляет никаких выходов, поэтому мне не нужно было включить что-либо для этого раздела.
Последняя часть обновления в Action.yml
это раздел входов. Я хочу позволить пользователям пройти периоды времени на каждый день недели, которые они хотят заблокировать изменения в некоторых филиалах. Поэтому я добавляю один вход на каждый день недели ( понедельник
, ‘, …, солнце
), но сделайте их все возможными.
В настоящее время действия GitHub разрешают только входы строки. Таким образом, хороший способ получения периодов времени — это разделенный запятыми список временных интервалов в формате, как это: 00:00-07: 00,16: 30-23: 59
Отказ Этот пример означает изменение блока с полуночи до 7 часов утра и с 16:30 до полуночи.
Пользователи также должны иметь возможность указать часовой пояс в течение периодов времени, поэтому я добавляю TZ
В качестве ввода, который принимает разницу во времени от UTC.
Теперь я закончил с определкой моего действия. Следующим шагом является реализация логики. Въездная точка для действия — SRC/Main.ts
Отказ Вот аннотированное содержание файла:
import * as core from '@actions/core' import {isInDowntime, getUTCAdjustments} from './check' const days = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'] async function run(): Promise{ // Get the time that the action is called. const currentDate = new Date() try { // Parse `tz` (time zone) from the inputs. const tz = parseFloat(core.getInput('tz')) // Make adjustments to the current time to make sure we are checking for the correct time zone. const utcAdjustments = getUTCAdjustments(tz) currentDate.setUTCHours(currentDate.getUTCHours() + utcAdjustments.hours) currentDate.setUTCMinutes( currentDate.getUTCMinutes() + utcAdjustments.minutes ) // We can set debugging info with `core.debug`. It helped me fix an issue I encountered when parsing the inputs. core.debug(`TZ: ${tz} - Day: ${currentDate.getUTCDay()}`) // Get the input for the current day of the week. If the input is not specified, it returns `undefined`. In such cases, fallback to an empty string. const downtimes = core.getInput(days[currentDate.getUTCDay()]) || '' core.debug(`Downtimes: ${downtimes}`) // We expect a comma-separated list of time periods, so split them by comma and check each time period with `isInDowntime` function. If the current time is in any of the time periods, throw an error and stop the workflow by calling `core.setFailed`. for (const downtime of downtimes.split(',')) { if (isInDowntime(currentDate, utcAdjustments, downtime)) { core.setFailed( `The PR cannot be merged at this time (${currentDate}) with the current settings (${downtime}).` ) } } } catch (error) { // If any other errors happen, stop the workflow by calling `core.setFailed`. This also logs the error message in the output of the workflow. core.setFailed(`Error: ${error.message}. Run date: ${currentDate}.`) } } run()
Как уже упоминалось в Действия/Типоприпечатка-действие Шаблон, большинство операций CI/CD включают асинхронные процессы, и именно поэтому Беги
это асинхронная функция.
Isindownteme
Это функция, которая принимает дату, настройки UTC и периода времени и проверки, если данное время в период времени. Его содержание не является заботой этого поста, но я добавил аннотированную версию здесь:
export const isInDowntime = ( date: Date, utcAdjustments: UTCAdjustments, downtime?: string ): boolean => { if (!downtime) { return false } // The regex pattern that captures the start and end hours and minutes of the time period. const result = /(?\d{2}):(? \d{2})-(? \d{2}):(? \d{2})/.exec( downtime ) // If the input time period does not match the pattern and returns null, throw an error. if (!result) { throw new Error('Invalid downtime') } const groups = result.groups as DowntimePattern // Parse the captured groups in the regex match results as integer. const fromHour = parseInt(groups.fromHour, 10) const fromMinute = parseInt(groups.fromMinute, 10) const toHour = parseInt(groups.toHour, 10) const toMinute = parseInt(groups.toMinute, 10) // Double check the sections of the time period and make sure they are parsed as valid numbers and not NaN. for (const num of [fromHour, fromMinute, toHour, toMinute]) { if (Number.isNaN(num)) { throw new Error('Invalid downtime') } } // The next three blocks make sure hours and minutes are valid (between 0 and 23 for hours and 0 and 59 for minutes), and the start time is before the end time. for (const hour of [fromHour, toHour]) { if (hour < 0 || hour > 23) { throw new Error('Invalid downtime') } } for (const minute of [fromMinute, toMinute]) { if (minute < 0 || minute > 59) { throw new Error('Invalid downtime') } } if (fromHour > toHour || (fromHour === toHour && fromMinute > toMinute)) { throw new Error('Invalid downtime') } // Create two date objects, one for the start time and the other for the end time. // Both objects must be in the current working date, with their hours and minutes adjusted for UTC. const start = Date.UTC( date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), fromHour - utcAdjustments.hours, fromMinute - utcAdjustments.minutes ) const end = Date.UTC( date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), toHour - utcAdjustments.hours, toMinute - utcAdjustments.minutes ) // Finally, check if the given date is between the start and end times. return date.getTime() >= start && date.getTime() <= end }
Я включил некоторые тесты в __тестс __/main.test.ts
Чтобы проверить логику, хотя мне, вероятно, нужно больше сценариев, чтобы покрыть краевые чехлы, в основном вокруг часовых поясов.
Последний шаг — обновить рабочий процесс Включено в шаблон, чтобы он работает с обновленным кодом. Этот рабочий процесс запускает две задания: первый тестирует код и компилирования и связывает его. Вторая работа использует сам код как часть рабочего процесса со следующими входами:
with: tz: -5 mon: 00:00-07:00,16:30-23:59 tue: 00:00-07:00,16:30-23:59 wed: 00:00-07:00,16:30-23:59 thu: 00:00-07:00,16:30-23:59 fri: 00:00-07:00,16:30-23:59 sat: 00:00-23:59 sun: 00:00-23:59
Эти входы устанавливают часовой пояс к центральному времени (-5) и изменениям блока до 7 часов утра и после 16:30 в будние дни и все дни в выходные дни.
Мне пришлось играть с конфигурацией несколько раз и вносить изменения в код, чтобы исправить ошибки, которые выдвинулись, когда я нажал мои изменения и завершил сломанный рабочий процесс. В конце концов, я получил его, работая, когда я увидел, что мой рабочий процесс не провалил из-за странных ошибок, но потому что я толкал изменения в выходные, которые я указываю как время простоя в рабочем процессе!
Перед публикацией акции на Github Marketplace я собрал короткую readme, описывающую то, что происходит, и тогда это было время выпуска!
Процесс публикации довольно легкий. Вы начинаете с разработки нового выпуска для вашего репо, похоже на то, как вы это делаете для любого проекта. Когда Github видит Action.yml
В вашем корне проекта он знает, что это действие и включает в себя соответствующий контрольный список на странице выпуска и говорит вам, есть ли вещи, которые вы можете сделать, чтобы улучшить свое действие, например, Включите значок брендинга или добавить readme! После завершения проекта выпуска нажмите «Публикация» и «Действие» отображается на рынке.
Проверьте Действия GitHub Действия для получения дополнительной информации и посмотрите их быстрое руководство к действиям JS здесь Отказ
Я также видел этот тщательный курс на GitHub Labout Lab. , Но я еще не пробовал.
Получайте удовольствие, создавая свои собственные действия GitHub!:)
Оригинал: «https://dev.to/ka7eh/my-first-github-action-579j»