Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Pelajari cara membuat aplikasi .NET yang dapat digunakan sebagai GitHub Action. GitHub Actions memungkinkan otomatisasi dan komposisi alur kerja. Dengan GitHub Actions, Anda dapat membuat, menguji, dan menyebarkan kode sumber dari GitHub. Selain itu, tindakan mengekspos kemampuan untuk berinteraksi secara terprogram dengan masalah, membuat permintaan pull, melakukan tinjauan kode, dan mengelola cabang. Untuk informasi selengkapnya tentang integrasi berkelanjutan dengan GitHub Actions, lihat Membangun dan menguji .NET.
Dalam tutorial ini, Anda akan belajar cara:
- Menyiapkan aplikasi .NET untuk GitHub Actions
- Menentukan input dan output tindakan
- Menyusun alur kerja
Prasyarat
- Akun GitHub
- .NET 6 SDK atau yang lebih baru
- Lingkungan pengembangan terintegrasi .NET (IDE)
- Jangan ragu untuk menggunakan IDE Visual Studio
Niat aplikasi
Aplikasi dalam tutorial ini melakukan analisis metrik kode dengan:
Memindai dan menemukan file proyek *.csproj dan *.vbproj .
Menganalisis kode sumber yang ditemukan dalam proyek-proyek ini untuk:
- Kompleksitas siklomatik
- Indeks keberlanjutan
- Kedalaman warisan
- Penggandengan kelas
- Jumlah baris kode sumber
- Perkiraan baris kode yang dapat dieksekusi
Membuat (atau memperbarui) file CODE_METRICS.md .
Aplikasi ini tidak bertanggung jawab untuk melakukan pull request dengan perubahan pada file CODE_METRICS.md. Perubahan ini dikelola sebagai bagian dari komposisi alur kerja.
Referensi ke kode sumber dalam tutorial ini memiliki bagian aplikasi yang dihilangkan untuk membuatnya lebih singkat. Kode aplikasi lengkap tersedia di GitHub.
Menjelajahi aplikasi
Aplikasi konsol .NET menggunakan paket NuGet untuk mengurai argumen ke dalam objek ActionInputs.
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]);
}
}
}
Kelas input tindakan sebelumnya menentukan beberapa input yang diperlukan agar aplikasi berhasil dijalankan. Konstruktor akan menulis "GREETINGS" nilai variabel lingkungan, jika tersedia di lingkungan eksekusi saat ini. Properti Name dan Branch diambil dan ditetapkan dari segmen terakhir sebuah string yang dipisahkan oleh "/".
Dengan kelas input tindakan yang ditentukan, fokus pada file 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);
}
File Program disederhanakan untuk kejelasan, untuk menjelajahi sumber kode lengkap, lihat pada Program.cs. Mekanisme yang sudah diterapkan menunjukkan kode boilerplate yang diperlukan untuk digunakan:
Proyek eksternal atau referensi paket dapat digunakan, dan terdaftar dengan injeksi dependensi.
Get<TService> adalah fungsi lokal statis, yang memerlukan instansIHost, dan digunakan untuk menyelesaikan layanan yang diperlukan. Dengan menggunakan CommandLine.Parser.Default singleton, aplikasi memperoleh instans parser dari args. Ketika argumen tidak dapat diurai, aplikasi keluar dengan kode keluar bukan nol. Untuk informasi selengkapnya, lihat Mengatur kode keluar untuk tindakan.
Ketika arg berhasil diurai, aplikasi dipanggil dengan benar dengan input yang diperlukan. Dalam hal ini, panggilan ke fungsionalitas StartAnalysisAsync utama dilakukan.
Untuk menulis nilai output, Anda harus mengikuti format yang dikenali oleh GitHub Actions: Mengatur parameter output.
Menyiapkan aplikasi .NET untuk GitHub Actions
GitHub Actions mendukung dua variasi pengembangan aplikasi, baik... ataupun
- JavaScript ( TypeScript opsional)
- Kontainer Docker (aplikasi apa pun yang berjalan di Docker)
Lingkungan virtual tempat GitHub Action dihosting mungkin atau mungkin tidak menginstal .NET. Untuk informasi tentang apa yang telah diinstal sebelumnya di lingkungan target, lihat GitHub Actions Virtual Environments. Meskipun dimungkinkan untuk menjalankan perintah .NET CLI dari alur kerja GitHub Actions, untuk membuat GitHub Action berbasis .NET yang berfungsi sepenuhnya, kami menyarankan Anda untuk mengemas aplikasi dalam kontainer. Untuk informasi selengkapnya, lihat Membuat kontainer aplikasi .NET.
Dockerfile
Dockerfile adalah serangkaian instruksi untuk membangun gambar. Untuk aplikasi .NET, Dockerfile biasanya berada di akar direktori di samping file solusi.
# 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" ]
Nota
Aplikasi .NET dalam tutorial ini bergantung pada .NET SDK sebagai bagian dari fungsionalitasnya. Dockerfile membuat sekumpulan lapisan Docker baru, independen dari yang sebelumnya. Dimulai dari nol dengan gambar SDK, dan menambahkan output build dari lapisan sebelumnya. Untuk aplikasi yang tidak memerlukan .NET SDK sebagai bagian dari fungsionalitasnya, mereka harus hanya mengandalkan .NET Runtime sebagai gantinya. Ini sangat mengurangi ukuran gambar.
FROM mcr.microsoft.com/dotnet/runtime:7.0
Peringatan
Perhatikan dengan cermat setiap langkah dalam Dockerfile, karena berbeda dari Dockerfile standar yang dibuat dari fungsionalitas "tambahkan dukungan docker". Secara khusus, beberapa langkah terakhir bervariasi dengan tidak menentukan yang baru WORKDIR yang akan mengubah jalur ke aplikasi ENTRYPOINT.
Langkah-langkah Dockerfile sebelumnya meliputi:
- Mengatur gambar dasar dari
mcr.microsoft.com/dotnet/sdk:7.0sebagai aliasbuild-env. - Menyalin konten dan menerbitkan aplikasi .NET:
- Aplikasi diterbitkan menggunakan
dotnet publishperintah .
- Aplikasi diterbitkan menggunakan
- Menerapkan label ke kontainer.
- Relayering gambar .NET SDK dari
mcr.microsoft.com/dotnet/sdk:7.0 - Menyalin hasil build yang diterbitkan dari
build-env. - Menentukan titik masuk, yang mendelegasikan ke
dotnet /DotNet.GitHubAction.dll.
Petunjuk / Saran
MCR adalah mcr.microsoft.com singkatan dari "Microsoft Container Registry", dan merupakan katalog kontainer sindikasi Microsoft dari hub Docker resmi. Untuk informasi selengkapnya, lihat Katalog kontainer sindikat Microsoft.
Perhatian
Jika Anda menggunakan file global.json untuk menyematkan versi SDK, Anda harus secara eksplisit merujuk ke versi tersebut di Dockerfile Anda. Misalnya, jika Anda telah menggunakan global.json untuk menyematkan versi 5.0.300SDK, Dockerfile Anda harus menggunakan mcr.microsoft.com/dotnet/sdk:5.0.300. Ini mencegah mengganggu GitHub Actions saat revisi minor baru dirilis.
Menentukan input dan output tindakan
Di bagian Jelajahi aplikasi, Anda mempelajari tentang kelasActionInputs. Objek ini mewakili input untuk GitHub Action. Agar GitHub mengenali bahwa repositori adalah GitHub Action, Anda harus memiliki file action.yml di akar repositori.
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 }}
File action.yml sebelumnya mendefinisikan:
-
namedandescriptiondalam GitHub Action -
branding, yang digunakan di GitHub Marketplace untuk membantu mengidentifikasi tindakan Anda secara lebih unik -
inputs, yang memetakan satu-ke-satu dengan kelasActionInputs -
outputs, yang dituliskan dalamProgramdan digunakan sebagai bagian dari Komposisi Alur Kerja - Simpul
runs, yang menginformasikan GitHub bahwa aplikasidockerdan argumen apa yang harus diteruskan kepada aplikasi tersebut
Untuk informasi selengkapnya, lihat Sintaks metadata untuk GitHub Actions.
Variabel lingkungan yang telah ditentukan sebelumnya
Dengan GitHub Actions, Anda akan mendapatkan banyak variabel lingkungan secara default. Misalnya, variabel GITHUB_REF akan selalu berisi referensi ke cabang atau tag yang memicu eksekusi alur kerja.
GITHUB_REPOSITORY memiliki nama pemilik dan repositori, misalnya, dotnet/docs.
Anda harus menjelajahi variabel lingkungan yang telah ditentukan sebelumnya dan menggunakannya dengan sesuai.
Komposisi alur kerja
Dengan aplikasi .NET yang telah dikontainerkan, dan input dan output tindakan yang telah ditentukan, Anda siap untuk menggunakan tindakan. GitHub Actions tidak perlu diterbitkan di GitHub Marketplace untuk digunakan. Alur kerja didefinisikan dalam direktori .github/workflows repositori sebagai file 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.'
Penting
Untuk GitHub Actions yang terkontainer, Anda harus menggunakan runs-on: ubuntu-latest. Untuk informasi selengkapnya, lihat Sintaks jobs.<job_id>.runs-onalur kerja .
File YAML alur kerja sebelumnya mendefinisikan tiga simpul utama:
- Alur
namekerja. Nama ini jugalah yang digunakan saat membuat lencana status alur kerja. - Simpul
onmenentukan kapan dan bagaimana tindakan dipicu. - Simpul
jobsmenguraikan berbagai pekerjaan dan langkah-langkah dalam setiap pekerjaan. Langkah-langkah individual menggunakan GitHub Actions.
Untuk informasi selengkapnya, lihat Membuat alur kerja pertama Anda.
Berfokus pada node steps , komposisinya lebih jelas:
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.'
jobs.steps mewakili komposisi alur kerja. Langkah-langkah diorkestrasi sedemikian rupa sehingga berurutan, komunikatif, dan tersusun. Dengan berbagai GitHub Actions yang mewakili langkah-langkah, masing-masing memiliki input dan output, alur kerja dapat dibuat.
Pada langkah-langkah sebelumnya, Anda dapat mengamati:
Pesan dicetak ke log alur kerja, saat dijalankan secara manual.
Langkah yang diidentifikasi sebagai
dotnet-code-metrics:-
uses: dotnet/samples/github-actions/DotNet.GitHubAction@mainadalah lokasi aplikasi .NET dalam kontainer dalam tutorial ini. -
envmembuat variabel lingkungan"GREETING", yang dicetak dalam pelaksanaan aplikasi. -
withmenentukan setiap input tindakan yang diperlukan.
-
Langkah kondisional bernama
Create pull requestdijalankan ketika langkahdotnet-code-metricsmenentukan sebuah parameter keluaran berupaupdated-metricsdengan nilaitrue.
Penting
GitHub memungkinkan pembuatan rahasia terenkripsi. Rahasia dapat digunakan dalam komposisi alur kerja, menggunakan sintaks ${{ secrets.SECRET_NAME }}. Dalam konteks GitHub Action, ada token GitHub yang secara otomatis diisi secara default: ${{ secrets.GITHUB_TOKEN }}. Untuk informasi selengkapnya, lihat Sintaks konteks dan ekspresi untuk Tindakan GitHub.
Satukan semuanya
Repositori GitHub dotnet/samples adalah rumah untuk banyak proyek kode sumber sampel .NET, termasuk aplikasi dalam tutorial ini.
File CODE_METRICS.md yang dihasilkan dapat dinavigasi. File ini mewakili hierarki proyek yang dianalisisnya. Setiap proyek memiliki bagian tingkat atas, dan emoji yang mewakili status keseluruhan kompleksitas siklomatik tertinggi untuk objek berlapis. Saat Anda menavigasi file, setiap bagian memaparkan peluang penelusuran dengan ringkasan setiap area. Markdown memiliki bagian yang dapat dilipat untuk kemudahan tambahan.
Hierarki berkembang dari:
- File proyek ke assembly
- Rakitan ke namespace
- Namespace ke tipe-bernama
- Setiap jenis bernama memiliki tabel, dan setiap tabel memiliki:
- Tautan ke nomor baris untuk bidang, metode, dan properti
- Peringkat individual untuk metrik kode
Sedang beraksi
Alur kerja menentukan bahwa ketika on sebuah push ke cabang main, tindakan dipicu untuk dijalankan. Saat berjalan, tab Tindakan di GitHub akan melaporkan aliran log langsung dari eksekusinya. Berikut adalah contoh log dari .NET code metrics eksekusi:
Peningkatan performa
Jika Anda mengikuti sampel, Anda mungkin telah memperhatikan bahwa setiap kali tindakan ini digunakan, tindakan ini akan melakukan build docker untuk gambar tersebut. Jadi, setiap pemicu memerlukan waktu tertentu untuk membangun kontainer sebelum menjalankannya. Sebelum merilis GitHub Actions Anda ke marketplace, Anda harus:
- (otomatis) Membangun gambar Docker
- Dorong gambar docker ke GitHub Container Registry (atau registri kontainer publik lainnya)
- Ubah tindakan untuk tidak membuat gambar, tetapi untuk menggunakan gambar dari registri publik.
# 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!!
Untuk informasi selengkapnya, lihat Dokumen GitHub: Bekerja dengan registri Kontainer.
Lihat juga
- Host Generik .NET
- Penyuntikan ketergantungan di .NET
- Nilai metrik kode
- GitHub Action sumber terbuka dibangun di .NET dengan alur kerja untuk membuat dan mengirim image docker secara otomatis.