Этот пост был первоначально опубликован в понедельник, 24 мая 2021 г. cloudwithchris.com .
Как вы, возможно, читали ранее, мой сайт Cloudwithchris.com размещено с использованием статических веб -сайтов Azure State. Общая модель при построении статических веб -сайтов — это контроль версий активов и использование непрерывной интеграции и непрерывной доставки для доставки визуализированного скомпилированного веб -сайта в Azure. Я недавно начал создавать с открытым исходным кодом .NET Core Command-Line Application, которое может принять файлы Hugo Yaml ввод, преобразовать содержимое файла в соответствующую отметку для поддерживаемых сторонних служб (в настоящее время dev.to и medium.com ), заменив локальные URL -адреса, добавив подходящие шорткоды рендеринга YouTube/твит, а затем отправляя непосредственно в API.
Вы можете увидеть, куда это идет. Поскольку у меня есть процесс непрерывной интеграции (CI) и непрерывного развертывания (CD) для развертывания моего производственного веб-сайта в Azure, я также хочу интегрировать перекрестные сообщения в сторонние услуги блогов в этот процесс. Вот почему я выбрал .NET Core Command-Line Application, так что полученный исполняемый файл может запустить кроссплатформенную. Это также означает, что я мог бы выполнить это исполняемое файл в рамках конвейера развертывания, будь то в Azure Tipelines, Github Actions, Jenkins, Gitlab и т. Д. Поскольку я использую действия GitHub для развертывания моего сайта в Azure, для меня имело смысл создать действие GitHub, которое я могу использовать в своем рабочем процессе GitHub Actions. Это именно то, о чем я буду говорить в этом посте в блоге!
Если вы еще не знали, каждое действие GitHub фактически является еще одним репозиторием GitHub. Поэтому всякий раз, когда вы используете действие/оформление заказа, вы на самом деле имеете в виду github.com/actions/checkout репозиторий. Каждый из этих «хранилища действий» будет иметь файл action.yml в корне репозитория, чтобы сообщить GitHub, что он представляет собой действие GitHub — подробнее об этом позже!
Давайте сначала рассмотрим варианты вокруг Создание действий GitHub Action Анкет Мы можем либо —
JavaScript Action
Возможно, мог работать, хотя я уже начал создавать приложение командной строки, поэтому он взял на себя зависимость от .net Основной. Эти действия JavaScript выполняются путем выполнения файлов JavaScript в «Репозитории действия» в контексте вашей кодовой базы. Итак, если бы я хотел пересечь свое облако с Cris Content, JavaScript, загруженное из другого репозитория, будет выполнено в моем Кризреддингтон/Cloudwithchris.com репозиторий. Это означает, что мне нужно было изобрести колесо, так как я уже начал свою реализацию с .net Основной. По этой причине был исключен подход к действию JavaScript. Подход JavaScript Action полезен, поскольку он может быть проведен на различных платформах GitHub Action Runner. Имейте это в виду, когда мы поговорим о действиях контейнера Docker позже.
Далее, Составное действие запуска
Анкет Это причудливый способ сказать «запустить серию шагов в командной линии». Это может быть вариант как .net Основные приложения могут быть выполнены в командной строке. Проблема с таким подходом заключается в том, что мы находимся в целом, каких зависимостей устанавливаются на бегуне GitHub Action в определенный момент времени, не в последнюю очередь, если кто-то управляет самостоятельным бегуном, у которого будет другой набор зависимостей и и версии. Я хочу, чтобы обслуживание этого проекта было максимально простым. Итак, по этой причине — я исключил действие композитного пробега.
Наконец, Docker Container Action
Анкет Это вариант, который я в конечном итоге выбрал. Если вы знакомы с контейнерами в качестве технологии, вы будете знать, что они могут в последовательном выполнении (а не доставке только приложения или дельты приложения, вы также отправляете зависимости контейнеров в изображении контейнера, что обеспечивает согласованность) Анкет Ключевой момент, который стоит отметить — действие контейнера Docker работает только на бегуне GitHub GitHub как задокументировано здесь Анкет Это не является важной проблемой, так как я хотел, чтобы исполняемый файл программы способен запускать кроссплатформенные, а не действие GitHub обязательно. Таким образом, это дает конечным пользователям возможность запустить приложение командной строки на любой платформе вручную. В качестве альтернативы они могут использовать действие GitHub в задании, которое использует бегун Linux. Если рабочий процесс действия конечного пользователя в основном основан на Windows или Mac, это не проблема. Они могут определить новую работу специально для перекрестных аспектов.
Отлично, поэтому у нас есть решение о том, как организовать приложение командной строки. Что дальше? Для действия контейнера Docker нам нужно два файла — A Dockerfile
и Файл метаданных действий
, также известный как action.yml
файл.
Если в прошлом вы создавали изображения Docker, то этот процесс не будет отличаться от любых других, которые вы построили. Для тех, кто новичок в Docker — DockerFile является набор инструкций по созданию изображения Docker. Вы указываете базовое изображение (другое изображение Docker), чтобы построить сверху, а затем укажите серию шагов, которые будут добавлены поверх этого изображения. Каждая инструкция — это еще один слой изображения, поэтому, когда вы смотрите на вывод шага сборки Docker, вы увидите множество хэшей, связанных с новым изображением для каждого слоя.
Как обычно, хорошая практика, в приведенном ниже примере используется многоэтапная сборка, чтобы гарантировать, что конечное получение изображения является легким и содержит только необходимые зависимости для эффективного запуска. Основной шаг сборки будет использовать изображение, которое содержит необходимые инструменты для составления исходного кода в необходимый двоичный приложение.
Таким образом, в следующем DockerFile будет работать многоступенчатая сборка —
- Первый этап будет:
- Используйте .NET Core SDK Docker Image в качестве базы (это изображение будет иметь все необходимые инструменты, необходимые для создания .NET .NET Основное приложение, поэтому будет больше изображения времени выполнения, которое будет использоваться позже). Псевдоним
Build-env
предоставляется для простоты ссылки позже в Dockerfile - Скопируйте файлы из локального каталога в изображение контейнера в рабочем состоянии.
- Запустить
Dotnet Publish
командование - Забегайте контейнер соответствующими метаданными (что является лучшей практикой для написания Dockerfiles ) Второй этап будет:
- Используйте .NET Core SDK Docker Image в качестве базы (это изображение будет иметь все необходимые инструменты, необходимые для создания .NET .NET Основное приложение, поэтому будет больше изображения времени выполнения, которое будет использоваться позже). Псевдоним
- Используйте .NET Основное изображение времени выполнения (это дает несколько преимуществ, включая уменьшение размера полученного изображения, поскольку оно не раздувается инструментами сборки, а также обеспечивает меньшую потенциальную поверхность атаки)
- Скопируйте содержимое папки/out из предыдущего этапа (
- build-env
) в текущий каталог в создаваемом изображении выполнения.
Установите точку входа в контейнер как - dotnet/hugocrossposter.dll
. Это означает, что контейнер будет работать только до тех пор, пока приложение командной строки придерживается запуска.
# Set the base image as the .NET 5.0 SDK (this includes the runtime) FROM mcr.microsoft.com/dotnet/sdk:5.0 as build-env # Copy everything and publish the release (publish implicitly restores and builds) COPY . ./ RUN dotnet publish ./src/HugoCrossPoster.csproj -c Release -o out --no-self-contained # Label the container LABEL maintainer="Chris Reddington" LABEL repository="https://github.com/chrisreddington/HugoCrossPoster" LABEL homepage="https://github.com/chrisreddington/HugoCrossPoster" # Label as GitHub action LABEL com.github.actions.name="Hugo Cross Poster" # Limit to 160 characters LABEL com.github.actions.description="This is a work in progress .NET Core Console App to ease cross posting from Hugo to alternate formats." # See branding: # https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#branding LABEL com.github.actions.icon="activity" LABEL com.github.actions.color="orange" # Relayer the .NET SDK, anew with the build output FROM mcr.microsoft.com/dotnet/sdk:5.0 COPY --from=build-env /out . ENTRYPOINT [ "dotnet", "/HugoCrossPoster.dll" ]
Это ни в коем случае не предназначено для того, чтобы стать учебником о том, как написать Dockerfile. Тем не менее, это хорошо проточенный путь, и в сообществе существует множество блестящих примеров. Давай, проверь их, если тебе интересно!
Далее, Файл метаданных действий
Также известен как action.yml
файл. Это определяет входы, выходы и основную точку входа для вашего действия. Схема этого файла четко определена в GitHub Actions Docs . Чтобы сделать это проще, я включил action.yml
Файл для моего Хьюго Креста Плакат Github Action. У него есть несколько основных компонентов —
- Серия метаданных об действии. Например, название, описание и брендинг.
- Набор ожидаемых
Вход
которые необходимы для действия GitHub. - Возможно иметь набор
выходы
, если вы планируете разоблачить информацию, которая будет передана другим действиям GitHub. Я не использую это в своем действии. A
запускает
свойство, которое указывает:- Тип действия GitHub, который мы определяем (то есть Docker, JavaScript и т. Д.)
- Точка входа нашего действия (в нашем случае
dockerfile
находится в том же каталоге, что иaction.yml
Так что это простоDockerfile
) - Набор аргументов, которые должны быть переданы в контейнер Docker. В этом случае это аргументы, которые передаются в .net Основное приложение командной строки. Если вы посмотрите на исходный код для приложения , вы заметите, что флаги соответствуют.
name: 'Hugo Crossposter' description: 'This is a work in progress .NET Core Console App to ease cross posting from Hugo to alternate formats.' branding: icon: activity color: orange inputs: directoryPath: description: 'Directory path of the content to be converted and crossposted.' required: true recursiveSubdirectories: description: 'Boolean (True/False) on whether Recursive Subdirectories should be used for file access' required: true default: 'false' originalPostInformation: description: 'Boolean (True/False) on whether the details of the original post (date/time, and canonical URL) should be included in the rendered markdown.' required: false default: 'false' logPayloadOutput: description: 'Boolean (True/False) on whether the output of the payload should also be outputted in the logs.' required: false default: 'false' searchPattern: description: 'The search string to match against the names of files in path. This parameter can contain a combination of valid literal path and wildcard (* and ?) characters, but it doesnt support regular expressions. Defaults to *.md.' required: false default: '*.md' baseUrl: description: 'Base URL of the website, not including protocol. e.g. www.cloudwithchris.com. This is used for converting any relative links to the original source, including the canonical URL.' required: true default: 'www.cloudwithchris.com' devtoToken: description: 'DevTo Integration Token. This is required if crossposting to DevTo, as it forms part of the URL for the API Call.' required: false devtoOrganization: description: 'DevTo Organization. This is not required. If you are posting as a user and want to associate the post with an organization, enter the organization ID (not username) here.' required: false mediumAuthorId: description: 'Medium Author ID. This is required if crossposting to medium, as it forms part of the URL for the API Call.' required: false mediumToken: description: 'Medium Integration Token. This is required to authorize to the Medium API.' required: false protocol: description: 'Protocol used on the website. Options are either HTTP or HTTPS. This is used for converting any relative links to the original source, including the canonical URL.' required: false runs: using: 'docker' image: 'Dockerfile' args: - "-f" - "${{ inputs.directoryPath }}" - "-r" - "${{ inputs.recursiveSubdirectories }}" - "-o" - "${{ inputs.originalPostInformation }}" - "-l" - "${{ inputs.logPayloadOutput }}" - "-s" - "${{ inputs.searchPattern }}" - "-u" - "${{ inputs.baseUrl }}" - "-d" - "${{ inputs.devtoToken }}" - "-g" - "${{ inputs.devtoOrganization }}" - "-a" - "${{ inputs.mediumAuthorId }}" - "-i" - "${{ inputs.mediumToken }}" - "-p" - "${{ inputs.protocol }}"
И в конечном итоге это волшебство, стоящая за созданием собственного действия GitHub. Вам нужен исходный код для вашего действия (то есть JavaScript, если вы используете действие GitHub на основе JavaScript, DockerFile и связанный код приложения, если вы используете действие GitHub на основе Docker, любые необходимые зависимости, если вы используете шаг составного запуска) Анкет
Есть несколько вещей, которые следует иметь в виду как автор действия GitHub. Я не сомневаюсь, что вы планируете стать отличным гражданином с открытым исходным кодом и хотите сохранить свое действие GitHub с открытым источником. Что произойдет, если вы обновите свое действие GitHub и внесете некоторые прерываемые изменения, как вы убедитесь, что не нарушаете рабочие процессы своих потребителей? Как и любая другая зависимость, мы используем управление версиями. Поскольку изменения вносятся в репозиторий GIT, мы можем пометить хэши коммита по номеру версии по мере необходимости. Это подробно объяснено в Использование управления релизами для действий Раздел в документах GitHub.
Если вы раньше использовали какие -либо действия GitHub, вы могли заметить, что в некоторых действиях указывается число после имени действия. Например, Использование: действия/проверка@v2
или Использование: Azure/Login@v1
. Это просто относится к тег GIT в репо. Вы сможете увидеть это в разделе «Выпуск» репозитория для действия GitHub (например, или Azure/Login выпуски )
Кроме того, обычно рекомендуется создать новое действие GitHub в новом репозитории GitHub. Как взято из документов GitHub — Если вы разрабатываете действие для использования других людей, мы рекомендуем сохранить действие в его собственном хранилище вместо того, чтобы объединить его с другим кодом приложения. Это позволяет вам вернуть, отслеживать и выпускать действие, как и любое другое программное обеспечение. .
Вот почему Hugrossposter находится в своем собственном хранилище, с «кодом приложения» для перекрестного плаката. Все это самостоятельно, и может быть версия как общая доставка/единица развертывания. Если вы планируете использовать приложение командной строки в собственной местной среде или на машине в другом месте — это абсолютно нормально. Если вы хотите использовать его как действие GitHub в вашем рабочем процессе, это тоже абсолютно хорошо!
Итак, вы идете — это показывает вам, как легко идти вперед и создать действие GitHub, основанное на .net Core Command-Line Application благодаря типу действия контейнера Docker. Если вы ищете дополнительное руководство, есть отличный пример на .СЕТЬ Документы что также помогло мне на пути к созданию моего действия GitHub для Hugocrossposter — так что слава команде, которая написала это!
С этим, спасибо, что прочитали этот пост в блоге — и я надеюсь, что это было полезно! Я хотел бы услышать, какие действия GitHub вы планируете на строительство! Будете ли вы использовать Docker и .net Core, возможно, JavaScript действие или составное шаг запуска? Дайте мне знать на Twitter, @reddobowen .
Еще раз спасибо, и до следующего — пока пока!
Оригинал: «https://dev.to/cloudwithchris/making-a-github-action-with-docker-and-net-core-cfj»