Oktatóanyag: GitHub-művelet létrehozása .NET-tel
Megtudhatja, hogyan hozhat létre egy GitHub-műveletként használható .NET-alkalmazást. A GitHub Actions lehetővé teszi a munkafolyamat automatizálását és összetételét. A GitHub Actions segítségével forráskódot hozhat létre, tesztelhet és helyezhet üzembe a GitHubról. Emellett a műveletek programozott módon kezelhetik a problémákat, lekéréses kérelmeket hozhatnak létre, kód-felülvizsgálatokat hajthatnak végre, és kezelhetik az ágakat. A GitHub Actions szolgáltatással való folyamatos integrációról további információt a .NET létrehozása és tesztelése című témakörben talál.
Ebben az oktatóanyagban az alábbiakkal fog megismerkedni:
- .NET-alkalmazás előkészítése a GitHub Actionshez
- Műveleti bemenetek és kimenetek definiálása
- Munkafolyamat összeállítása
Előfeltételek
- GitHub-fiók
- A .NET 6 SDK vagy újabb
- .NET integrált fejlesztési környezet (IDE)
Az alkalmazás szándéka
Az oktatóanyagban szereplő alkalmazás a következőkkel végzi el a kódmetrika elemzését:
*.csproj és *.vbproj projektfájlok vizsgálata és felderítése.
A felderített forráskód elemzése a következő projektekben:
- Ciklonmatikus összetettség
- Karbantarthatósági index
- Az öröklés mélysége
- Osztálykapcsoló
- Forráskódsorok száma
- Végrehajtható kód hozzávetőleges sora
CODE_METRICS.md fájl létrehozása (vagy frissítése).
Az alkalmazás nem felelős azért, hogy lekéréses kérelmet hozzon létre a CODE_METRICS.md fájl módosításaival. Ezeket a módosításokat a munkafolyamat-összeállítás részeként kezeli a rendszer.
Az oktatóanyag forráskódjára mutató hivatkozások az alkalmazás bizonyos részeit kihagyják a rövidség kedvéért. A teljes alkalmazáskód elérhető a GitHubon.
Az alkalmazás bemutatása
A .NET-konzolalkalmazás a CommandLineParser
NuGet-csomag használatával elemzi az argumentumokat az ActionInputs
objektumban.
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]);
}
}
}
Az előző műveletbemeneti osztály több szükséges bemenetet határoz meg az alkalmazás sikeres futtatásához. A konstruktor megírja a "GREETINGS"
környezeti változó értékét, ha az aktuális végrehajtási környezetben elérhető. A Name
rendszer elemzi és Branch
hozzárendeli a tulajdonságokat egy tagolt sztring "/"
utolsó szegmenséből.
A definiált műveletbeviteli osztályban a Program.cs fájlra kell összpontosítani.
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);
}
A Program
fájl egyszerűbb a rövidség kedvéért, hogy megismerje a teljes mintaforrást, lásd: Program.cs. A mechanika a használathoz szükséges kazánlemez-kódot mutatja be:
Külső projekt- vagy csomaghivatkozások használhatók, és függőséginjektálással regisztrálhatók. Ez Get<TService>
egy statikus helyi függvény, amely megköveteli a IHost
példányt, és a szükséges szolgáltatások feloldására szolgál. CommandLine.Parser.Default
A singleton használatával az alkalmazás lekéri a példányt parser
a args
. Ha az argumentumok nem elemezhetők, az alkalmazás nem nulla kilépési kóddal lép ki. További információ: Kilépési kódok beállítása műveletekhez.
Az argek sikeres elemzésekor az alkalmazás helyesen lett meghívva a szükséges bemenetekkel. Ebben az esetben az elsődleges funkció StartAnalysisAsync
hívása történik.
Kimeneti értékek írásához a GitHub Actions által felismert formátumot kell követnie: Kimeneti paraméter beállítása.
A .NET-alkalmazás előkészítése a GitHub Actionshez
A GitHub Actions az alkalmazásfejlesztés két változatát támogatja, vagy
- JavaScript (opcionálisan TypeScript)
- Docker-tároló (bármely, a Dockeren futó alkalmazás)
Előfordulhat, hogy a GitHub-művelet üzemeltetett virtuális környezetében telepítve lehet a .NET. A célkörnyezetben előre telepített adatokról a GitHub Actions Virtuális környezetek című témakörben olvashat bővebben. Bár .NET CLI-parancsokat is futtathat a GitHub Actions munkafolyamataiból, a teljesebb működés érdekében. NET-alapú GitHub Action, javasoljuk, hogy tárolóba helyezi az alkalmazást. További információ: .NET-alkalmazás tárolóba helyezése.
A Dockerfile
A Dockerfile a rendszerképek létrehozásához szükséges utasítások készlete. .NET-alkalmazások esetén a Dockerfile általában a megoldásfájl melletti könyvtár gyökerében található.
# 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" ]
Megjegyzés:
Az oktatóanyagban szereplő .NET-alkalmazás a .NET SDK-ra támaszkodik a funkciói részeként. A Dockerfile az előzőektől független új Docker-rétegeket hoz létre. Az SDK-lemezképpel kezdődik, és hozzáadja az előző rétegcsoport buildkimenetét. Az olyan alkalmazások esetében, amelyek nem igénylik a .NET SDK-t a működésük részeként, inkább csak a .NET-futtatókörnyezetre kell támaszkodniuk. Ez jelentősen csökkenti a kép méretét.
FROM mcr.microsoft.com/dotnet/runtime:7.0
Figyelmeztetés
Ügyeljen a Dockerfile minden lépésére, mivel ez eltér a docker-támogatás hozzáadása funkcióból létrehozott szokásos Docker-fájltól. Az utolsó néhány lépés különösen úgy változik, hogy nem ad meg egy újat WORKDIR
, amely megváltoztatná az alkalmazás ENTRYPOINT
elérési útját.
Az előző Dockerfile-lépések a következők:
- Az alaprendszerkép
mcr.microsoft.com/dotnet/sdk:7.0
beállítása aliaskéntbuild-env
. - A tartalom másolása és a .NET-alkalmazás közzététele:
- Az alkalmazás közzététele a
dotnet publish
paranccsal történik.
- Az alkalmazás közzététele a
- Címkék alkalmazása a tárolóra.
- A .NET SDK-rendszerkép továbbítása innen:
mcr.microsoft.com/dotnet/sdk:7.0
- A közzétett buildkimenet másolása a
build-env
. - Annak a belépési pontnak a meghatározása, amely a következőre delegálható
dotnet /DotNet.GitHubAction.dll
: .
Tipp.
Az MCR a mcr.microsoft.com
"Microsoft Container Registry" (Microsoft Container Registry) nevet jelöli, és a Microsoft konzorciális tárolókatalógusa a hivatalos Docker Hubból. További információt a Microsoft syndicates tárolókatalógusában talál.
Figyelem
Ha global.json fájllal rögzíti az SDK-verziót, kifejezetten hivatkoznia kell erre a verzióra a Dockerfile-ban. Ha például global.json használatával rögzítette az SDK-verziót5.0.300
, a Dockerfile-nak kell használniamcr.microsoft.com/dotnet/sdk:5.0.300
. Ez megakadályozza a GitHub Actions feltörését egy új alverzió kiadásakor.
Műveleti bemenetek és kimenetek definiálása
Az Alkalmazás felfedezése szakaszban megismerhette az osztálytActionInputs
. Ez az objektum a GitHub-művelet bemeneteit jelöli. Ahhoz, hogy a GitHub felismerje, hogy az adattár egy GitHub-művelet, rendelkeznie kell egy action.yml fájllal az adattár gyökerénél.
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 }}
Az előző action.yml fájl a következőket határozza meg:
- A
name
GitHub-művelet ésdescription
a - A
branding
GitHub Marketplace-en a művelet egyedibb azonosításához használt - Az
inputs
, amely egy-az-egyhez megfelelteti az osztálytActionInputs
- A
outputs
munkafolyamat-összeállításbanProgram
és annak részeként írt, - A
runs
csomópont, amely közli a GitHubbal, hogy az alkalmazás egydocker
alkalmazás, és milyen argumentumokat kell átadni neki
További információ: GitHub Actions metaadatszintaxisa.
Előre definiált környezeti változók
A GitHub Actions használatával alapértelmezés szerint sok környezeti változót fog kapni. A változó GITHUB_REF
például mindig tartalmaz egy hivatkozást a munkafolyamat futtatását kiváltó ágra vagy címkére. GITHUB_REPOSITORY
tulajdonosi és adattárnévvel rendelkezik, dotnet/docs
például .
Meg kell vizsgálnia az előre definiált környezeti változókat, és ennek megfelelően kell használnia őket.
Munkafolyamat-összeállítás
A .NET-alkalmazás tárolóba van adva, és a műveleti bemenetek és kimenetek definiálva vannak, készen áll a művelet felhasználására. A GitHub Actionst nem kell közzétenni a GitHub Marketplace-en a használathoz. A munkafolyamatok yaML-fájlokként vannak definiálva az adattár .github/workflows könyvtárában.
# 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.'
Fontos
Tárolóalapú GitHub Actions esetén a következőket kell használnia runs-on: ubuntu-latest
: . További információ: Munkafolyamat szintaxisa jobs.<job_id>.runs-on
.
Az előző munkafolyamat YAML-fájlja három elsődleges csomópontot határoz meg:
- A
name
munkafolyamat. Ez a név használatos munkafolyamat-állapotjelvény létrehozásakor is. - A
on
csomópont határozza meg, hogy mikor és hogyan aktiválódik a művelet. - A
jobs
csomópont az egyes feladatok különböző feladatait és lépéseit tagolja. Az egyes lépések a GitHub Actionst használják fel.
További információ: Az első munkafolyamat létrehozása.
A csomópontra összpontosítva steps
a kompozíció nyilvánvalóbb:
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.'
Ez jobs.steps
a munkafolyamat-összetételt jelöli. A lépések úgy vannak vezénylve, hogy szekvenciálisak, kommunikatívak és összeállíthatók legyenek. A lépések különböző GitHub Actions-műveletekkel, amelyek mindegyike bemenetekkel és kimenetekkel rendelkezik, munkafolyamatok is összeállíthatók.
Az előző lépésekben a következőket figyelheti meg:
Az adattár ki van véve.
Manuálisan futtatott üzenet lesz kinyomtatva a munkafolyamat-naplóba.
A következőként
dotnet-code-metrics
azonosított lépés:uses: dotnet/samples/github-actions/DotNet.GitHubAction@main
a tárolóalapú .NET-alkalmazás helye ebben az oktatóanyagban.env
létrehoz egy környezeti változót"GREETING"
, amely az alkalmazás végrehajtása során lesz kinyomtatva.with
az egyes szükséges műveletbemeneteket adja meg.
Egy elnevezett
Create pull request
feltételes lépés akkor fut, ha adotnet-code-metrics
lépés egy kimeneti paramétertupdated-metrics
ad meg, amelynek értéke a következőtrue
.
Fontos
A GitHub lehetővé teszi titkosított titkos kódok létrehozását. A titkos kulcsok a munkafolyamat-összeállításban használhatók a ${{ secrets.SECRET_NAME }}
szintaxis használatával. A GitHub-művelet kontextusában van egy GitHub-jogkivonat, amely alapértelmezés szerint automatikusan fel van töltve: ${{ secrets.GITHUB_TOKEN }}
. További információ: A GitHub Actions környezet- és kifejezésszintaxisa.
Az alkalmazás összeállítása
A dotnet/samples GitHub-adattár számos .NET-mintaforráskód-projektnek ad otthont, beleértve az oktatóanyagban szereplő alkalmazást is.
A létrehozott CODE_METRICS.md fájl navigálásra alkalmas. Ez a fájl az elemzett projektek hierarchiáját jelöli. Minden projekt rendelkezik egy legfelső szintű szakaszsal és egy hangulatjelekkel, amelyek a beágyazott objektumok legmagasabb ciklomatikus összetettségének általános állapotát képviselik. A fájlban való navigálás során minden szakasz részletezési lehetőségeket tesz elérhetővé az egyes területek összegzésével. A Markdown összecsukható szakaszokkal rendelkezik, mint további kényelem.
A hierarchia a következőből halad előre:
- Projektfájl szerelvényhez
- Szerelvény a névtérbe
- Névtér nevesített típushoz
- Minden névvel ellátott típushoz tartozik egy tábla, és mindegyik táblához tartozik:
- Mezők, metódusok és tulajdonságok sorszámaira mutató hivatkozások
- Egyedi minősítések kódmetrikákhoz
Működés közben
A munkafolyamat azt határozza meg, hogy on
push
az main
ágra irányuló művelet futtatása aktiválva legyen. Amikor fut, a GitHub Műveletek lapja jelenti a végrehajtás élő naplóstreamjét. Íme egy példanapló a .NET code metrics
futtatásból:
Teljesítménynövelő fejlesztések
Ha követte a mintát, észrevehette, hogy minden alkalommal, amikor ezt a műveletet használja, docker-buildet készít a rendszerképhez. Így minden eseményindítónak van egy kis ideje a tároló összeállítására a futtatás előtt. Mielőtt közzétenné a GitHub Actionst a piactéren, a következőket kell elvégeznie:
- (automatikusan) A Docker-rendszerkép létrehozása
- A Docker-rendszerkép leküldése a GitHub Container Registrybe (vagy bármely más nyilvános tárolóregisztrációs adatbázisba)
- Módosítsa a műveletet úgy, hogy ne a rendszerképet hozza létre, hanem egy nyilvános beállításjegyzékből származó lemezképet használjon.
# 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!!
További információ: GitHub Docs: A tárolóregisztrációs adatbázis használata.
Kapcsolódó információk
- .NET Általános gazdagép
- Függőséginjektálás a .NET-ben
- Kódmetrikák értékei
- Nyílt forráskódú GitHub Action buildelés a .NET-ben a Docker-rendszerkép automatikus létrehozására és leküldésére szolgáló munkafolyamattal .