Tutorial: Buat Tindakan GitHub dengan .NET
Pelajari cara membuat aplikasi .NET yang bisa digunakan sebagai Tindakan GitHub. Tindakan GitHub memungkinkan otomatisasi serta komposisi alur kerja. Dengan GitHub Actions, Anda bisa membangun, menguji, serta menyebarkan kode Anda dari GitHub. Selain itu, tindakan mengekspos kemampuan untuk berinteraksi secara terprogram dengan masalah, membuat permintaan pull, melakukan tinjauan kode, serta mengelola cabang. Untuk informasi selengkapnya mengenai integrasi berkelanjutan dengan GitHub Actions, lihat Membangun dan menguji .NET.
Dalam tutorial ini, Anda akan mempelajari cara:
- Menyiapkan aplikasi .NET untuk Tindakan GitHub
- Menentukan input serta output tindakan
- Membuat alur kerja
Prasyarat
- Akun GitHub
- .NET 6 SDK atau yang lebih baru
- Lingkungan pengembangan terintegrasi .NET (IDE)
- Jangan sungkan untuk menggunakan Visual Studio IDE
Niat dari 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 ini untuk:
- Kompleksitas siklomatik
- Indeks keberlanjutan
- Kedalaman pewarisan
- Pemasangan kelas
- Jumlah baris kode sumber
- Perkiraan baris kode yang dapat dieksekusi
Membuat (atau memperbarui) file CODE_METRICS.md.
Aplikasi ini tidak bertanggung jawab untuk membuat permintaan pull 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 keringkasan. Kode aplikasi lengkap tersedia di GitHub.
Menjelajahi aplikasi
Aplikasi konsol .NET menggunakan paket CommandLineParser
NuGet untuk mengurai argumen ke dalam objekActionInputs
.
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 dieksekusi. Konstruktor akan menulis nilai variabel lingkungan "GREETINGS"
, apabila tersedia di lingkungan eksekusi saat ini. Properti Name
dan Branch
diurai dan ditetapkan dari segmen terakhir dari string "/"
yang dibatasi.
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 agar mudah, untuk menjelajahi sumber sampel lengkap, lihat Program.cs. Mekanisme di tempat menunjukkan kode boilerplate yang dibutuhkan untuk menggunakan:
Referensi proyek atau paket eksternal dapat digunakan, serta terdaftar dengan injeksi dependensi. Get<TService>
adalah fungsi lokal statik, yang memerlukan instansIHost
, serta digunakan untuk menyelesaikan layanan yang diperlukan. Dengan singleton CommandLine.Parser.Default
, aplikasi mendapatkan 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 argumen berhasil diurai, aplikasi dipanggil dengan benar dengan input yang dibutuhkan. Dalam hal ini, panggilan ke fungsionalitas utama StartAnalysisAsync
dilakukan.
Untuk menulis nilai output, Anda harus mengikuti format yang dikenali oleh GitHub Actions: Mengatur parameter output.
Menyiapkan aplikasi .NET untuk Tindakan GitHub
Tindakan GitHub mendukung dua variasi pengembangan aplikasi, baik
- JavaScript ( TypeScript opsional)
- Kontainer Docker (aplikasi apa pun yang berjalan di Docker)
Lingkungan virtual tempat Tindakan GitHub dihosting mungkin menginstal atau mungkin tidak menginstal .NET. Untuk informasi mengenai 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 fungsi yang lebih sepenuhnya . GitHub Action berbasis NET, kami sarankan Anda membuat kontainer aplikasi. Untuk informasi selengkapnya, lihat Menampung aplikasi .NET.
Dockerfile
Dockerfile adalah serangkaian instruksi untuk membangun sebuah 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" ]
Catatan
Aplikasi .NET dalam tutorial ini bergantung pada .NET SDK sebagai bagian dari fungsionalitasnya. Dockerfile membuat sekumpulan lapisan Docker baru, independen dari yang sebelumnya. Ini dimulai dari awal dengan gambar SDK, dan menambahkan output build dari set lapisan sebelumnya. Untuk aplikasi yang tidak memerlukan .NET SDK sebagai bagian dari fungsionalitasnya, mereka harus mengandalkan .NET Runtime saja sebagai gantinya. Ini sangat mengurangi ukuran dari 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.0
sebagai aliasbuild-env
. - Menyalin konten dan menerbitkan aplikasi .NET:
- Aplikasi ini diterbitkan menggunakan perintah
dotnet publish
.
- Aplikasi ini diterbitkan menggunakan perintah
- Menerapkan label ke kontainer.
- Menyampaikan gambar .NET SDK dari
mcr.microsoft.com/dotnet/sdk:7.0
- Menyalin output build yang diterbitkan dari
build-env
. - Menentukan titik masuk, yang mendelegasikan ke
dotnet /DotNet.GitHubAction.dll
.
Tip
MCR dalam mcr.microsoft.com
adalah 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, apabila Anda telah menggunakan global.json untuk menyematkan versi 5.0.300
SDK, Dockerfile Anda harus menggunakan mcr.microsoft.com/dotnet/sdk:5.0.300
. Ini mencegah melanggar GitHub Actions ketika revisi minor baru dirilis.
Menentukan input serta output tindakan
Di bagian Jelajahi aplikasi, Anda mempelajari tentang kelas ActionInputs
. Objek ini mewakili input untuk Tindakan GitHub. Agar GitHub mengenali bahwa repositori adalah Tindakan GitHub, 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:
name
dandescription
dari Tindakan GitHubbranding
, yang digunakan di GitHub Marketplace untuk membantu mengidentifikasi tindakan Anda secara lebih unikinputs
, yang memetakan satu-ke-satu dengan kelasActionInputs
outputs
, yang ditulis dalamProgram
serta digunakan sebagai bagian dari komposisi Alur Kerja- Simpul
runs
, yang memberi tahu GitHub bahwa aplikasi adalah aplikasidocker
dan argumen apa yang harus diteruskan ke dalamnya
Untuk informasi selengkapnya, lihat Sintaks metadata untuk Tindakan GitHub.
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 menggunakan variabel lingkungan dengan sesuai.
Komposisi alur kerja
Dengan aplikasi .NET yang dikontainerisasi, serta input dan output tindakan yang ditentukan, Anda siap untuk menghabiskan tindakan. GitHub Actions tidak perlu dipublikasikan di GitHub Marketplace untuk digunakan. Alur kerja didefinisikan dalam direktori .github/workflows dari 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 Tindakan GitHub dalam kontainer, Anda harus menggunakan runs-on: ubuntu-latest
. Untuk informasi selengkapnya, lihat Sintaks Ruang Kerjajobs.<job_id>.runs-on
.
File YAML alur kerja sebelumnya mendefinisikan tiga simpul utama:
name
dari alur kerja. Nama ini juga yang digunakan saat membuat lencana status alur kerja.- Simpul
on
menentukan kapan serta bagaimana tindakan dipicu. - Simpul
jobs
menguraikan berbagai pekerjaan serta langkah-langkah dalam setiap pekerjaan. Langkah-langkah individual mengonsumsi Tindakan GitHub.
Untuk informasi selengkapnya, lihat Membuat alur kerja pertama Anda.
Berfokus pada simpul 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 skemanya sehingga mereka berurutan, komunikatif, serta dapat disusun. Dengan berbagai Tindakan GitHub yang mewakili langkah-langkah, masing-masing memiliki input dan output, alur kerja dapat disusun.
Pada langkah sebelumnya, Anda bisa mengamati:
Repositori diperiksa.
Pesan dicetak ke log alur kerja, ketika dijalankan secara manual.
Langkah yang diidentifikasi sebagai
dotnet-code-metrics
:uses: dotnet/samples/github-actions/DotNet.GitHubAction@main
adalah lokasi aplikasi .NET dalam kontainer dalam tutorial ini.env
membuat variabel lingkungan"GREETING"
, yang dicetak dalam eksekusi aplikasi.with
menentukan masing-masing input tindakan yang diperlukan.
Langkah kondisional, bernama
Create pull request
berjalan saat langkahdotnet-code-metrics
menentukan parameter output dariupdated-metrics
dengan nilaitrue
.
Penting
GitHub memungkinkan pembuatan dari rahasia terenkripsi. Rahasia dapat digunakan dalam komposisi alur kerja, menggunakan sintaks ${{ secrets.SECRET_NAME }}
. Dalam konteks Tindakan GitHub, ada token GitHub yang secara otomatis diisi secara default: ${{ secrets.GITHUB_TOKEN }}
. Untuk informasi selengkapnya, lihat Konteks dan sintaks 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, serta emoji yang mewakili status keseluruhan kompleksitas siklomatik tertinggi untuk objek berlapis. Saat Anda menavigasi file, setiap bagian memaparkan peluang penelusuran paling detail dengan ringkasan dari setiap area. Markdown mempunyai bagian yang dapat diciutkan sebagai kenyamanan tambahan.
Hierarki berlangsung dari:
- Proyek file ke assembly
- Assembly ke namespace layanan
- Namespace layanan ke jenis-bernama
- Setiap jenis bernama memiliki tabel, dan setiap tabel memiliki:
- Tautan ke nomor baris untuk bidang, metode, serta properti
- Peringkat individual untuk metrik kode
Sedang bertindak
Alur kerja menentukan bahwa on
adalah push
ke cabang main
, tindakan dipicu untuk dijalankan. Saat berjalan, tab Tindakan di GitHub akan melaporkan aliran log langsung eksekusinya. Berikut adalah contoh log dari eksekusi .NET code metrics
:
Peningkatan performa
Jika Anda mengikuti contoh, Anda mungkin memperhatikan bahwa setiap kali tindakan ini digunakan, tindakan ini akan melakukan pembangunan docker untuk gambar tersebut. Jadi, setiap pemicu diberikan beberapa waktu untuk membangun kontainer sebelum menjalankannya. Sebelum merilis GitHub Actions Anda ke marketplace, Anda harus:
- (secara otomatis) Membangun gambar Docker
- Mendorong gambar docker ke GitHub Container Registry (atau registri kontainer publik lainnya)
- Ubah tindakan agar tidak membangun gambar, tetapi 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.
Baca juga
- Host Umum .NET
- Injeksi dependensi di .NET
- Nilai metrik kode
- Pembangunan GitHub Action sumber terbuka di .NET dengan alur kerja untuk membangun dan mendorong gambar docker secara otomatis.