Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Dowiedz się, jak utworzyć aplikację platformy .NET, która może być używana jako akcja usługi GitHub. Funkcja GitHub Actions umożliwia automatyzację i kompozycję przepływu pracy. Za pomocą funkcji GitHub Actions można tworzyć, testować i wdrażać kod źródłowy z usługi GitHub. Ponadto akcje ukazują możliwość programistycznej interakcji z kwestiami, tworzenia pull requestów, przeprowadzania przeglądów kodu i zarządzania gałęziami. Aby uzyskać więcej informacji na temat ciągłej integracji z funkcją GitHub Actions, zobacz Kompilowanie i testowanie platformy .NET.
W tym poradniku nauczysz się, jak:
- Przygotowywanie aplikacji .NET dla funkcji GitHub Actions
- Definiowanie danych wejściowych i wyjściowych akcji
- Tworzenie przepływu pracy
Wymagania wstępne
- Konto usługi GitHub
- Pakiet .NET 6 SDK lub późniejszy
- Zintegrowane środowisko projektowe (IDE) platformy .NET
- Możesz korzystać z środowiska IDE programu Visual Studio
Intencja aplikacji
Aplikacja w tym samouczku wykonuje analizę metryk kodu przez:
Skanowanie i odnajdywanie plików projektów *.csproj i *.vbproj .
Analizowanie odnalezionego kodu źródłowego w następujących projektach:
- Złożoność cyklotyczna
- Indeks możliwości konserwacji
- Głębokość dziedziczenia
- Sprzęganie klas
- Liczba wierszy kodu źródłowego
- Przybliżone wiersze kodu wykonywalnego
Tworzenie (lub aktualizowanie) pliku CODE_METRICS.md .
Aplikacja nie jest odpowiedzialna za utworzenie pull request z wprowadzonymi zmianami w pliku CODE_METRICS.md. Te zmiany są zarządzane w ramach kompozycji przepływu pracy.
Odwołania do kodu źródłowego w tym samouczku zawierają fragmenty aplikacji pominięte w celu zwięzłości. Pełny kod aplikacji jest dostępny w witrynie GitHub.
Eksplorowanie aplikacji
Aplikacja konsolowa platformy .NET używa CommandLineParser pakietu NuGet do analizowania argumentów w ActionInputs obiekcie.
using CommandLine;
namespace DotNet.GitHubAction;
public class ActionInputs
{
string _repositoryName = null!;
string _branchName = null!;
public ActionInputs()
{
if (Environment.GetEnvironmentVariable("GREETINGS") is { Length: > 0 } greetings)
{
Console.WriteLine(greetings);
}
}
[Option('o', "owner",
Required = true,
HelpText = "The owner, for example: \"dotnet\". Assign from `github.repository_owner`.")]
public string Owner { get; set; } = null!;
[Option('n', "name",
Required = true,
HelpText = "The repository name, for example: \"samples\". Assign from `github.repository`.")]
public string Name
{
get => _repositoryName;
set => ParseAndAssign(value, str => _repositoryName = str);
}
[Option('b', "branch",
Required = true,
HelpText = "The branch name, for example: \"refs/heads/main\". Assign from `github.ref`.")]
public string Branch
{
get => _branchName;
set => ParseAndAssign(value, str => _branchName = str);
}
[Option('d', "dir",
Required = true,
HelpText = "The root directory to start recursive searching from.")]
public string Directory { get; set; } = null!;
[Option('w', "workspace",
Required = true,
HelpText = "The workspace directory, or repository root directory.")]
public string WorkspaceDirectory { get; set; } = null!;
static void ParseAndAssign(string? value, Action<string> assign)
{
if (value is { Length: > 0 } && assign is not null)
{
assign(value.Split("/")[^1]);
}
}
}
Poprzednia klasa danych wejściowych akcji definiuje kilka wymaganych danych wejściowych, aby aplikacja została pomyślnie uruchomiona. Konstruktor zapisze wartość zmiennej środowiskowej "GREETINGS" , jeśli jest ona dostępna w bieżącym środowisku wykonywania. Właściwości Name i Branch są analizowane i przypisywane z ostatniego segmentu "/" rozdzielanego ciągu.
W przypadku zdefiniowanej klasy danych wejściowych akcji skoncentruj się na pliku Program.cs .
using System.Text;
using CommandLine;
using DotNet.GitHubAction;
using DotNet.GitHubAction.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using static CommandLine.Parser;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddGitHubActionServices();
using IHost host = builder.Build();
ParserResult<ActionInputs> parser = Default.ParseArguments<ActionInputs>(() => new(), args);
parser.WithNotParsed(
errors =>
{
host.Services
.GetRequiredService<ILoggerFactory>()
.CreateLogger("DotNet.GitHubAction.Program")
.LogError("{Errors}", string.Join(
Environment.NewLine, errors.Select(error => error.ToString())));
Environment.Exit(2);
});
await parser.WithParsedAsync(
async options => await StartAnalysisAsync(options, host));
await host.RunAsync();
static async ValueTask StartAnalysisAsync(ActionInputs inputs, IHost host)
{
// Omitted for brevity, here is the pseudo code:
// - Read projects
// - Calculate code metric analytics
// - Write the CODE_METRICS.md file
// - Set the outputs
var updatedMetrics = true;
var title = "Updated 2 projects";
var summary = "Calculated code metrics on two projects.";
// Do the work here...
// Write GitHub Action workflow outputs.
var gitHubOutputFile = Environment.GetEnvironmentVariable("GITHUB_OUTPUT");
if (!string.IsNullOrWhiteSpace(gitHubOutputFile))
{
using StreamWriter textWriter = new(gitHubOutputFile, true, Encoding.UTF8);
textWriter.WriteLine($"updated-metrics={updatedMetrics}");
textWriter.WriteLine($"summary-title={title}");
textWriter.WriteLine($"summary-details={summary}");
}
await ValueTask.CompletedTask;
Environment.Exit(0);
}
Plik Program jest uproszczony w celu zwięzłości, aby zapoznać się z pełnym źródłem przykładu, zobacz Program.cs. Obecna mechanika demonstruje kod szablonowy wymagany do użycia.
Można użyć zewnętrznych odwołań do projektów lub pakietów i zarejestrować przy użyciu wstrzykiwania zależności. Funkcja lokalna Get<TService> jest statyczna, wymaga wystąpienia IHost i jest używana do rozwiązywania wymaganych usług. W przypadku singletonu CommandLine.Parser.Default, aplikacja pobiera instancję parser z args. Gdy argumenty nie mogą być parsowane, aplikacja kończy działanie z niezerowym kodem wyjścia. Aby uzyskać więcej informacji, zobacz Ustawianie kodów zakończenia dla działań.
Po pomyślnym przeanalizowaniu argumentów aplikacja została wywołana poprawnie z wymaganymi danymi wejściowymi. W takim przypadku jest wykonywane wywołanie funkcji podstawowej StartAnalysisAsync .
Aby zapisać wartości wyjściowe, należy postępować zgodnie z formatem rozpoznawanym przez funkcję GitHub Actions: ustawianie parametru wyjściowego.
Przygotowywanie aplikacji .NET dla funkcji GitHub Actions
Funkcja GitHub Actions obsługuje dwie odmiany tworzenia aplikacji, albo
- JavaScript (opcjonalnie TypeScript)
- Kontener platformy Docker (dowolna aplikacja działająca na platformie Docker)
Środowisko wirtualne, w którym hostowana jest akcja GitHub, może mieć zainstalowaną platformę .NET lub jej nie mieć. Aby uzyskać informacje o tym, co jest wstępnie zainstalowane w środowisku docelowym, zobacz GitHub Actions Virtual Environments (Środowiska wirtualne funkcji GitHub Actions). Chociaż można uruchamiać polecenia .NET CLI z przepływów pracy GitHub Actions, rekomendujemy konteneryzację aplikacji dla bardziej funkcjonalnej akcji GitHub opartej na platformie .NET. Aby uzyskać więcej informacji, zobacz Containerize a .NET app (Konteneryzowanie aplikacji platformy .NET).
Plik Dockerfile
Plik Dockerfile to zestaw instrukcji tworzenia obrazu. W przypadku aplikacji .NET plik Dockerfile zwykle znajduje się w katalogu głównym obok pliku solution.
# Set the base image as the .NET 7.0 SDK (this includes the runtime)
FROM mcr.microsoft.com/dotnet/sdk:7.0@sha256:d32bd65cf5843f413e81f5d917057c82da99737cb1637e905a1a4bc2e7ec6c8d as build-env
# Copy everything and publish the release (publish implicitly restores and builds)
WORKDIR /app
COPY . ./
RUN dotnet publish ./DotNet.GitHubAction/DotNet.GitHubAction.csproj -c Release -o out --no-self-contained
# Label the container
LABEL maintainer="David Pine <david.pine@microsoft.com>"
LABEL repository="https://github.com/dotnet/samples"
LABEL homepage="https://github.com/dotnet/samples"
# Label as GitHub action
LABEL com.github.actions.name="The name of your GitHub Action"
# Limit to 160 characters
LABEL com.github.actions.description="The description of your GitHub Action."
# 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:7.0@sha256:d32bd65cf5843f413e81f5d917057c82da99737cb1637e905a1a4bc2e7ec6c8d
COPY --from=build-env /app/out .
ENTRYPOINT [ "dotnet", "/DotNet.GitHubAction.dll" ]
Uwaga / Notatka
Aplikacja .NET w tym samouczku opiera się na SDK platformy .NET jako część swojej funkcjonalności. Plik Dockerfile tworzy nowy zestaw warstw platformy Docker niezależnie od poprzednich. Zaczyna od zera, używając obrazu SDK, i dodaje wynik kompilacji z poprzedniego zestawu warstw. W przypadku aplikacji, które nie wymagają zestawu SDK platformy .NET w ramach ich funkcji, należy zamiast tego polegać tylko na środowisku uruchomieniowym platformy .NET. Znacznie zmniejsza to rozmiar obrazu.
FROM mcr.microsoft.com/dotnet/runtime:7.0
Ostrzeżenie
Zwróć szczególną uwagę na każdy krok w pliku Dockerfile, ponieważ różni się on od standardowego pliku Dockerfile utworzonego na podstawie funkcji "dodaj obsługę platformy Docker". W szczególności kilka ostatnich kroków różni się, ponieważ nie określono nowego WORKDIR, co spowodowałoby zmianę ścieżki do aplikacji ENTRYPOINT.
Powyższe kroki pliku Dockerfile obejmują:
- Ustawianie obrazu podstawowego z
mcr.microsoft.com/dotnet/sdk:7.0jako aliasubuild-env. - Kopiowanie zawartości i publikowanie aplikacji .NET:
- Aplikacja jest publikowana przy użyciu
dotnet publishpolecenia .
- Aplikacja jest publikowana przy użyciu
- Stosowanie etykiet do kontenera.
- Przekazywanie obrazu zestawu SDK platformy .NET z
mcr.microsoft.com/dotnet/sdk:7.0 - Skopiowanie danych wyjściowych opublikowanej kompilacji z pliku
build-env. - Definiowanie punktu wejścia, który deleguje do
dotnet /DotNet.GitHubAction.dll.
Wskazówka
MCR w mcr.microsoft.com to skrót od "Microsoft Container Registry" (Rejestr Kontenerów Microsoft) i jest to katalog kontenerów firmy Microsoft dostępny w oficjalnym Docker Hub. Aby uzyskać więcej informacji, zobacz Katalog kontenerów Microsoft.
Ostrzeżenie
Jeśli używasz pliku global.json do przypinania wersji zestawu SDK, należy jawnie odwołać się do tej wersji w pliku Dockerfile. Jeśli na przykład użyto global.json do przypinania wersji 5.0.300zestawu SDK, plik Dockerfile powinien używać polecenia mcr.microsoft.com/dotnet/sdk:5.0.300. Zapobiega to uszkodzeniu funkcji GitHub Actions po wydaniu nowej poprawki pomocniczej.
Definiowanie danych wejściowych i wyjściowych akcji
W sekcji Eksploruj aplikację przedstawiono klasę ActionInputs . Ten obiekt reprezentuje dane wejściowe akcji usługi GitHub. Aby usługa GitHub rozpoznała, że repozytorium jest akcją usługi GitHub, musisz mieć plik action.yml w katalogu głównym repozytorium.
name: 'The title of your GitHub Action'
description: 'The description of your GitHub Action'
branding:
icon: activity
color: orange
inputs:
owner:
description:
'The owner of the repo. Assign from github.repository_owner. Example, "dotnet".'
required: true
name:
description:
'The repository name. Example, "samples".'
required: true
branch:
description:
'The branch name. Assign from github.ref. Example, "refs/heads/main".'
required: true
dir:
description:
'The root directory to work from. Examples, "path/to/code".'
required: false
default: '/github/workspace'
outputs:
summary-title:
description:
'The title of the code metrics action.'
summary-details:
description:
'A detailed summary of all the projects that were flagged.'
updated-metrics:
description:
'A boolean value, indicating whether or not the action updated metrics.'
runs:
using: 'docker'
image: 'Dockerfile'
args:
- '-o'
- ${{ inputs.owner }}
- '-n'
- ${{ inputs.name }}
- '-b'
- ${{ inputs.branch }}
- '-d'
- ${{ inputs.dir }}
Powyższy plik action.yml definiuje:
- Akcja
nameidescriptionusługi GitHub - Element
branding, który jest używany w witrynie GitHub Marketplace, aby ułatwić bardziej unikalne określenie tożsamości twojej akcji -
inputs, który mapuje jeden do jednego z klasąActionInputs - Element
outputs, który jest zapisywany wProgrami używany jako część kompozycji przepływu pracy - Węzeł
runs, który informuje usługę GitHub, że aplikacja jest aplikacjądockeri jakie argumenty mają być przekazywane do niej
Aby uzyskać więcej informacji, zobacz Składnia metadanych dla funkcji GitHub Actions.
Wstępnie zdefiniowane zmienne środowiskowe
Dzięki funkcji GitHub Actions domyślnie uzyskasz wiele zmiennych środowiskowych . Na przykład zmienna GITHUB_REF będzie zawsze zawierać odwołanie do gałęzi lub tagu, który wyzwolił przebieg przepływu pracy.
GITHUB_REPOSITORY ma nazwę właściciela i repozytorium, na przykład dotnet/docs.
Należy zapoznać się ze wstępnie zdefiniowanymi zmiennymi środowiskowymi i użyć ich odpowiednio.
Kompozycja przepływu pracy
Po tym, jak aplikacja .NET została konteneryzowana, a dane wejściowe i wyjściowe akcji są zdefiniowane, jesteś gotowy na skorzystanie z akcji. Nie trzeba publikować GitHub Actions w GitHub Marketplace, aby je użyć. Przepływy pracy są definiowane w katalogu .github/workflows repozytorium jako pliki YAML.
# The name of the work flow. Badges will use this name
name: '.NET code metrics'
on:
push:
branches: [ main ]
paths:
- 'github-actions/DotNet.GitHubAction/**' # run on all changes to this dir
- '!github-actions/DotNet.GitHubAction/CODE_METRICS.md' # ignore this file
workflow_dispatch:
inputs:
reason:
description: 'The reason for running the workflow'
required: true
default: 'Manual run'
jobs:
analysis:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v3
- name: 'Print manual run reason'
if: ${{ github.event_name == 'workflow_dispatch' }}
run: |
echo 'Reason: ${{ github.event.inputs.reason }}'
- name: .NET code metrics
id: dotnet-code-metrics
uses: dotnet/samples/github-actions/DotNet.GitHubAction@main
env:
GREETINGS: 'Hello, .NET developers!' # ${{ secrets.GITHUB_TOKEN }}
with:
owner: ${{ github.repository_owner }}
name: ${{ github.repository }}
branch: ${{ github.ref }}
dir: ${{ './github-actions/DotNet.GitHubAction' }}
- name: Create pull request
uses: peter-evans/create-pull-request@v4
if: ${{ steps.dotnet-code-metrics.outputs.updated-metrics }} == 'true'
with:
title: '${{ steps.dotnet-code-metrics.outputs.summary-title }}'
body: '${{ steps.dotnet-code-metrics.outputs.summary-details }}'
commit-message: '.NET code metrics, automated pull request.'
Ważne
W przypadku konteneryzowanych funkcji GitHub Actions wymagane jest użycie polecenia runs-on: ubuntu-latest. Aby uzyskać więcej informacji, zobacz Składnia jobs.<job_id>.runs-onprzepływu pracy .
Powyższy plik YAML przepływu pracy definiuje trzy węzły podstawowe:
- Przepływ
namepracy. Ta nazwa jest również używana podczas tworzenia wskaźnika stanu przepływu pracy. - Węzeł
ondefiniuje, kiedy i jak jest wyzwalana akcja. - Węzeł
jobsprzedstawia różne zadania i kroki w ramach każdego zadania. Poszczególne kroki korzystają z funkcji GitHub Actions.
Aby uzyskać więcej informacji, zobacz Tworzenie pierwszego przepływu pracy.
Skupiając się na węźle steps, struktura staje się bardziej oczywista.
steps:
- uses: actions/checkout@v3
- name: 'Print manual run reason'
if: ${{ github.event_name == 'workflow_dispatch' }}
run: |
echo 'Reason: ${{ github.event.inputs.reason }}'
- name: .NET code metrics
id: dotnet-code-metrics
uses: dotnet/samples/github-actions/DotNet.GitHubAction@main
env:
GREETINGS: 'Hello, .NET developers!' # ${{ secrets.GITHUB_TOKEN }}
with:
owner: ${{ github.repository_owner }}
name: ${{ github.repository }}
branch: ${{ github.ref }}
dir: ${{ './github-actions/DotNet.GitHubAction' }}
- name: Create pull request
uses: peter-evans/create-pull-request@v4
if: ${{ steps.dotnet-code-metrics.outputs.updated-metrics }} == 'true'
with:
title: '${{ steps.dotnet-code-metrics.outputs.summary-title }}'
body: '${{ steps.dotnet-code-metrics.outputs.summary-details }}'
commit-message: '.NET code metrics, automated pull request.'
Obiekt jobs.steps reprezentuje kompozycję przepływu pracy. Kroki są orkiestrowane w taki sposób, że są sekwencyjne, komunikatywne i komponowalne. W przypadku różnych funkcji GitHub Actions reprezentujących kroki każdy z nich ma dane wejściowe i wyjściowe, można tworzyć przepływy pracy.
W poprzednich krokach można obserwować:
Repozytorium zostało wyewidencjonowane.
Komunikat jest drukowany w dzienniku przepływu pracy po ręcznym uruchomieniu.
Krok zidentyfikowany jako
dotnet-code-metrics:-
uses: dotnet/samples/github-actions/DotNet.GitHubAction@mainjest lokalizacją konteneryzowanej aplikacji .NET w tym samouczku. -
envTworzy zmienną środowiskową"GREETING", która jest drukowana podczas wykonywania aplikacji. -
withokreśla każde z wymaganych danych wejściowych akcji.
-
Krok warunkowy o nazwie
Create pull requestjest uruchamiany, gdydotnet-code-metricskrok określa parametrupdated-metricswyjściowy z wartościątrue.
Ważne
Usługa GitHub umożliwia tworzenie zaszyfrowanych wpisów tajnych. Wpisy tajne mogą być używane w kompozycji przepływu pracy przy użyciu ${{ secrets.SECRET_NAME }} składni. W kontekście akcji usługi GitHub istnieje token usługi GitHub, który jest domyślnie wypełniany automatycznie: ${{ secrets.GITHUB_TOKEN }}. Aby uzyskać więcej informacji, zobacz Składnia kontekstu i wyrażenia dla funkcji GitHub Actions.
Połącz wszystko
Repozytorium dotnet/samples w witrynie GitHub zawiera wiele przykładowych projektów kodu źródłowego platformy .NET, w tym aplikację używaną w niniejszym samouczku.
Wygenerowany plik CODE_METRICS.md jest możliwy do nawigacji. Ten plik reprezentuje hierarchię analizowanych projektów. Każdy projekt ma sekcję najwyższego poziomu i emoji reprezentujące ogólny stan najwyższej złożoności cyklatycznej dla zagnieżdżonych obiektów. Podczas nawigowania po pliku każda sekcja uwidacznia możliwości przechodzenia do szczegółów z podsumowaniem każdego obszaru. Markdown ma zwijane sekcje dla dodatkowej wygody.
Hierarchia rozpoczyna się od:
- Plik projektu do kompilacji
- Zestaw do przestrzeni nazw
- Przestrzeń nazw do jakiegoś zdefiniowanego typu
- Każdy nazwany typ ma tabelę, a każda tabela ma następujące elementy:
- Łącza do numerów wierszy dla pól, metod i właściwości
- Indywidualne klasyfikacje metryk kodu
W akcji
Przepływ pracy określa, że on do pushmain gałęzi akcja jest wyzwalana do uruchomienia. Po uruchomieniu karta Akcje w usłudze GitHub będzie raportować na żywo strumień dziennika jego wykonywania. Oto przykładowy log z .NET code metrics procesu:
Ulepszenia wydajności
Jeśli śledziłeś przykład, mogłeś zauważyć, że za każdym razem, gdy używana jest ta akcja, wykonywana jest komenda docker build dla danego obrazu. Każdy wyzwalacz musi poświęcić czas na zbudowanie kontenera przed jego uruchomieniem. Przed udostępnieniem funkcji GitHub Actions na platformie handlowej należy wykonać następujące czynności:
- (automatycznie) Kompilowanie obrazu platformy Docker
- Wypchnij obraz Docker do GitHub Container Registry (lub dowolnego innego publicznego rejestru kontenerów)
- Zmień akcję, aby nie skompilować obrazu, ale użyć obrazu z rejestru publicznego.
# Rest of action.yml content removed for readability
# using Dockerfile
runs:
using: 'docker'
image: 'Dockerfile' # Change this line
# using container image from public registry
runs:
using: 'docker'
image: 'docker://ghcr.io/some-user/some-registry' # Starting with docker:// is important!!
Aby uzyskać więcej informacji, zobacz GitHub Docs: Praca z rejestrem kontenerów.
Zobacz także
- Gospodarz ogólny .NET
- Iniekcja zależności w .NET
- Wartości metryk kodu
- Kompilacja akcji usługi GitHub typu open source na platformie .NET z przepływem pracy umożliwiającym automatyczne kompilowanie i wypychanie obrazu platformy Docker.