За эти годы я использовал несколько разных решений CI для моих скромных общественных проектов: Трэвис , Приложение и в конечном итоге лазурные трубопроводы.
Первоначально мне понравилась идея разделения CI/CD, чтобы избежать страшного блокировки поставщика и освободить меня, чтобы изменить поставщика SCC по желанию, но мне никогда не нравилось всегда посещать внешний сайт. Действия GitHub интересны для проектов, размещенных на GitHub, поскольку это интегрированное решение, аналогичное тому, которое предлагается конкурентами, такими как Gitlab.
Здесь я мигрирую один из моих существующих проектов .NET в GitHub Actions, но только детали специфичны для .NET, и большинство должно быть одинаково применимо к другим проектам.
Основы
В одном из ваших репозиториев вы можете щелкнуть Действия В таблице, а затем Установите этот рабочий процесс кнопка для инициализации .github/Workflows/*. YML
Файл на основе содержимого репо. Начальные рабочие процессы происходят из шаблонов в Действия GitHub/стартовые потоки и выглядеть похоже на Этот рабочий процесс для .net :
name: .NET Core # Trigger event on: # Run on a push or pull request to default branch (usually master) push: branches: [ $default-branch ] pull_request: branches: [ $default-branch ] # Jobs that run in parallel jobs: build: runs-on: ubuntu-latest # Steps that run sequentially steps: # git checkout repo - uses: actions/checkout@v2 # Install dotnet - name: Setup .NET Core uses: actions/setup-dotnet@v1 with: dotnet-version: 3.1.101 # Build and run tests - name: Build run: | dotnet restore dotnet build --configuration Release --no-restore - name: Test run: dotnet test --no-restore --verbosity normal
Рабочие процессы запускаются событиями и запускают один или несколько Работа в параллели. Работа — это набор последовательных шаги это либо сценарий оболочки, либо действие.
на:
Определяет события, которые запускают рабочий процесс. События могут быть чем угодно От толкания с клиентом GIT, создание выпуска на GitHub, периодических таймеров и многого другого.
Runs-on:
Определяет виртуальную среду, размещающую бегун рабочего процесса (то есть Windows, Linux или MacOS).
использует:
Определяет многоразовое действие (например, setup-dotnet ), чтобы позаботиться о шагах шаблонов, общих для сценариев CI/CD. Они могут быть определены в: в том же репо, публичных репо или опубликованных изображений Docker.
с:
передает параметры ключевой стоимости действий.
запустить:
Выполняет командные линии на оболочке. запустить:
| (с трубой) допускает несколько строк команд.
GitHub предоставляет Введение и Синтаксическая документация Анкет
Несколько платформ
Одним из первых изменений, которые я сделал, было создание и тестирование на нескольких платформах:
jobs: build: strategy: matrix: os: [windows-2019, ubuntu-18.04, macos-10.15] runs-on: ${{ matrix.os }} env: DOTNET_NOLOGO: true DOTNET_CLI_TELEMETRY_OPTOUT: true DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true steps: # ... - name: Code coverage if: ${{ matrix.os }} == 'ubuntu-18.04' uses: codecov/codecov-action@v1 # ...
Стратегия:
и Матрица:
Позвольте вам создать несколько заданий из одного определения. Здесь настройка каждого из «Windows», «Ubuntu» и «macos» значений из ОС:
к $ {{matrix.os}}
так Runs-on:
выполняет задание на всех трех ОС. Аналогично можно использовать для тестирования с несколькими времени запуска/фреймворков/компиляторов, конфигураций отладки/выпуска/профиля и т. Д.
env:
Устанавливает переменные среды на всех этапах работы.
if:
Включает работу или шаг только при условии, указанном выражение Анкет $ {{}}
Необязательно с if:
, вы также можете написать if: matrix.os
Анкет
Покрытие кода
Я ранее использовал OpenCover к инструменту .NET Projects. У Microsoft есть хорошая статья Детализация покрытия кода для модульных тестов .NET. Они используют Покрытие что теперь, кажется, является решением de-fact .NET, учитывая, что тестовые проекты XUNIT, созданные с помощью dotnet new xunit
автоматически добавьте ссылку на Coverlet.collector Анкет
Коверлет имеет 3 различных способа профиля проектов. Первый подход хорошо интегрируется, используя MSBuild ( Docs ):
# Add package reference to coverlet.msbuild in test project dotnet add tests/tests.csproj package coverlet.msbuild # Run tests and generate `coverage.json` dotnet test /p:CollectCoverage=true
Второй подход использует Глобальный инструмент :
# Install global tool dotnet tool install --global coverlet.console # Run tests coverlet tests/bin/Debug/netcoreapp3.1/tests.dll --target dotnet --targetargs "test --no-build"
Обязательно включите --нет-сборка
или сгенерированный отчет будет пустым. Согласно Этот блог Инструменты покрытия существующей сборки, так что вы не хотите Dotnet Test
Восстановление и замена его.
Есть третий подход, где вы используете «Datacollector» (как показано в статье MS). Коверлет предоставляет информацию Сравнение подходов а также Связанные недостатки Анкет
Теперь, когда у вас есть данные о покрытии, вы захотите создать отчет с чем -то вроде Reportgenerator , или облачное решение, как Codecov Как я буду здесь.
Codecov предоставляет Codecov-Action Для легкой интеграции с действиями GitHub:
steps: # ... - name: Test run: dotnet test --verbosity normal /p:CollectCoverage=true /p:CoverletOutputFormat=lcov - name: Code coverage if: matrix.os == 'ubuntu-18.04' uses: codecov/codecov-action@v1 with: files: ./tests/coverage.info flags: unittests
Если Codecov сообщит «отчеты о покрытии ошибок, вы останетесь, вы будете смотреть на бесполезную:
В моем случае, несмотря на Казалось бы, поддержка json (По умолчанию, произведенный Coverlet) Codecov не смог его обработать. Добавление /п: SoipletOutputFormat = LCOV
на тестовый запуск исправил его.
В зависимости от среды CI, структуры тестирования и т. Д. Codecov может быть не в состоянии обработать отчеты о покрытии без Фиксирование пути Анкет Это среди других параметров конфигурации может быть размещено в Codecov.yml
(который можно даже размещать в .github/
). Смотрите Codecov.yml Ссылка Для получения полной информации.
Значки
Поговорим о Flair Анкет Значки обеспечивают простой способ следить за вашим проектом:
Самый простой способ получить значок сборки — это открыть файл рабочего процесса или запустить, а затем нажмите ···> Создать значок статуса Чтобы сгенерировать уценку, аналогичную:
![](https://github.com/USER/PROJECT/workflows/WORKFLOW_NAME/badge.svg)
Проверьте Документация для специфики и дополнительных вариантов.
Для Codecov откройте репозиторий, затем Настройки> Значок Анкет В качестве альтернативы, вы можете Создайте значок непосредственно из действий Анкет
Нативный код
Я также хочу, чтобы действия создали некоторые нативные двоичные файлы. Даже если у вас нет собственного кода, этот же подход может использоваться для многоплатформенного тестирования или для создания посредничных выходов/артефактов.
Как раньше , мы можем использовать Docker и QEMU на Linux, чтобы легко построить бинарные файлы с конкретной платформой без перекрестной компиляции. Суть создает Dockerfile, как:
# Start with Debian for arm32 FROM multiarch/debian-debootstrap:armhf-buster AS arm32v7 # Install required software RUN apt-get update && apt-get install -y \ build-essential \ clang \ cmake RUN mkdir -p build && cd build \ # Build arm32 binary && cmake -G "Unix Makefiles" .. \ && make \ # Copy out of container to host && cp libnng.so /runtimes
Вместо того, чтобы смешивать мои декларативные действия рабочими процессом с большим количеством ветвления и специфичных для платформы махинаций, мне нравится перемещать логику в отдельный сценарий.
build_nng.ps1
позаботитесь об этих конкретных деталях здания:
if ($IsLinux) { # Register QEmu to handle unsupported binaries docker run --rm --privileged multiarch/qemu-user-static:register # Build our docker image docker build -t build-nng Dockerfile # Mount `/runtimes` and run image docker run -i -t --rm -v "$PWD/nng.NETCore/runtimes:/runtimes" build-nng } else { if ($is_windows) { cmake -A $arch -G "Visual Studio 16 2019" -DBUILD_SHARED_LIBS=ON -DNNG_TESTS=OFF -DNNG_TOOLS=OFF .. cmake --build . --config Release $dll = "Release/nng.dll" } else { cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DNNG_TESTS=OFF -DNNG_TOOLS=OFF .. make -j2 $dll = "libnng.dylib" } Copy-Item $dll "$runtimes/$path/native" -Force }
Создайте еще один рабочий процесс действия GitHub:
on: workflow_dispatch: inputs: nng_tag: description: 'NNG version' required: true jobs: build: strategy: matrix: os: [windows-2019, ubuntu-18.04, macos-10.15] runs-on: ${{ matrix.os }} steps: - name: Checkout nng.NET uses: actions/checkout@v2 - name: Build run: | ./scripts/build_nng.ps1 -nng_tag ${{ github.event.inputs.nng_tag }}
Этот рабочий процесс запускается workflow_dispatch
событие с Входные данные:
параметры, которые могут быть вручную запустить через ui github:
github.event
является частью Контекст о рабочем процессе запуска Анкет Среди других значений он содержит nng_tag:
от запуска события.
workflow_dispatch
также может быть Запускается http :
curl \ -X POST \ -H "Accept: application/vnd.github.v3+json" \ https://api.github.com/repos/$USER/$REPO/actions/workflows/$WORKFLOW/dispatches \ -d '{"inputs": {"nng_tag": "v1.3.0"}, "ref": "master"}' \ # For authorization, must add one of: -u $USER:$TOKEN #OR -H "Authorization: Bearer $TOKEN" #OR -H "Authorization: Token $TOKEN"
Эквивалент в PowerShell:
$SECURE_TOKEN=ConvertTo-SecureString -String $TOKEN -AsPlainText Invoke-WebRequest ` -Method Post ` -Headers @{accept= 'application/vnd.github.v3+json'} ` -Uri https://api.github.com/repos/$USER/$REPO/actions/workflows/$WORKFLOW/dispatches ` -Body (ConvertTo-Json @{inputs=@{nng_tag="v1.3.0"}; ref= "master"}) ` # For authorization, must add one of: -Authentication OAuth -Token $SECURE_TOKEN # OR -Authentication Bearer -Token $SECURE_TOKEN # OR by replacing above `-Headers` -Headers @{authorization= "Token $TOKEN"; accept= 'application/vnd.github.v3+json'}
Смотрите «Начало работы с API REST: аутентификация» Для получения дополнительной информации и подробностей о создании токенов GitHub API. Похоже, что ручные события должны работать, даже если рабочий процесс не в филиале по умолчанию, но Похоже, есть проблемы
Если есть промежуточный артефакт, который вы хотите вернуть в проект или сборку, Действия/проверка@v2
Облегчает работу с git :
# ... steps: - run: | git config user.name ${{ username }} git config user.email ${{ email }} git add . git commit -m "generated" git push
После настройки user.name
и user.email
, подтолкните изменения в филиал или сделайте больше всего, что еще больше, подходящее для вашего проекта.
Вы также можете Прикрепите артефакты сборки с Действия/upload-artifact
:
- name: Archive artifacts uses: actions/upload-artifact@v2 with: path: | nng.NETCore/runtimes/**/* !nng.NETCore/runtimes/any/**/* if-no-files-found: error
Пакет и опубликовать
Последний шаг — упаковка и выпуск реестра Nuget, как мы используется для вручную Анкет
Упрощенный скрипт:
param( [string]$Version, [string]$NugetApiKey, [string]$CertBase64, [string]$CertPassword ) $ErrorActionPreference = "Stop" # Strip the leading "v". E.g. "v1.3.2-rc0" => "1.3.2-rc0" $Version = $Version -replace "^v","" # Build nupkg dotnet pack --configuration Release -p:Version=$Version # Get list of build nupkgs $packages = Get-ChildItem "./bin/Release/*.nupkg" # Download nuget.exe $Nuget = "./nuget.exe" Invoke-WebRequest https://dist.nuget.org/win-x86-commandline/latest/nuget.exe -OutFile $Nuget # Create temporary code-signing certificate from base64-encoded string $tempCert = New-TemporaryFile [IO.File]::WriteAllBytes($tempCert.FullName, [Convert]::FromBase64String($CertBase64)) # Sign nupkg foreach ($pkg in $packages) { & $Nuget sign $pkg -Timestamper http://sha256timestamp.ws.symantec.com/sha256/timestamp -CertificatePath $tempCert.FullName -CertificatePassword $CertPassword -Verbosity quiet } # Delete temporary code-signing certificate $tempCert.Delete() # Upload nupkg to nuget foreach ($pkg in $packages) { dotnet nuget push $pkg -k $NugetApiKey -s https://api.nuget.org/v3/index.json }
Есть Несколько вариантов управления .NET Версия Анкет Я решил установить всю версию здесь, в Time Build с Dotnet Pack -p: версия = $ версия
, но вместо этого вы можете сохранить его в файлах проекта под управлением источника, только установите суффикс с Dotnet Build-version-suffix
, или какая -то комбинация их.
Чтобы подписать пакет, вы все еще нужно nuget:
nuget.exe sign-Timestamper http://sha256timestamp.ws.symantec.com/sha256/timestamp -CertificatePath
Для предоставления сертификата подписания кода действиям, которые вы можете BASE64 кодировать это и рассматривать его как один из секретов сборки (как показано ниже). Это означает, что мы должны декодировать его во временный файл перед запуском Nuget.
Дополнительные ресурсы, связанные с упаковкой/публикацией .NET:
- QuickStart: создать и опубликовать стандартный пакет Net (Dotnet CLI)
- Создать пакеты: создать пакет (Dotnet CLI)
- Создать пакеты: подписать пакет
- Публикуйте пакеты: опубликовать пакет
Рабочий процесс упаковки:
on: release: types: [published] workflow_dispatch: inputs: version: required: true jobs: build: runs-on: windows-2019 # ... - name: Package shell: pwsh run: | # Get the version $version = "${{ github.event_name }}" == "release" ? "${{ github.event.release.tag_name }}" : "${{ github.event.inputs.version }}" # Package and upload to nuget ./scripts/nupkg.ps1 -Version $version -CertBase64 ${{ secrets.CODE_SIGN_CERT_BASE64 }} -CertPassword ${{ secrets.CODE_SIGN_CERT_PASSWORD }} -NugetApiKey ${{ secrets.NUGET_API_KEY }}
Здесь я использую В: релиз:
запустить рабочий процесс в выпусках GitHub; Публикуйте релиз, и пакеты появляются в Nuget.
Я хочу $ версия
исходить из: git тег, связанный с выпуском, или из поставленного inputs.version
При отправке вручную. Мы могли бы использовать if:
Чтобы обеспечить альтернативные реализации шага, но, поскольку это просто значение одной переменной, кажется, что в скрипте легче разрешить.
Секреты
Контекст обеспечивает доступ к значениям, созданным в репозитории GitHub с Настройки> Секреты> Новый секрет репозитория Анкет Идея — Избегайте хранения конфиденциальной информации (Например, пароли) в общественных местах, а действия делают дополнительный шаг, чтобы очистить их из журналов.
Вместо (или в дополнение к) подталкивать вашу посылку в реестр, вы также можете Загрузите его в качестве актива выпуска прикреплено к выпуску.
Плавник
Я думаю, что это служит хорошим началом моей миграции в действии GitHub. Действительно, я едва поцарапал поверхность, так как еще не изучал действия сообщества, написав свои собственные действия, самостоятельные бегуны и гораздо больше.
Оригинал: «https://dev.to/jeikabu/publishing-non-trivial-net-with-github-actions-53ef»