Open5

actions/runner

雪猫雪猫

動かす

まずは動かしてみる。

ソースからビルド

runner/contribute.md at main · actions/runner

Windows
git clone https://github.com/actions/runner
cd runner
cd ./src
./dev.cmd layout
./dev.cmd build
./dev.cmd test

runner 配下に以下のディレクトリが作成される。
_layout が本体。

_dotnetsdk/
_downloads/
_layout/

起動

自己ホストランナーの追加 - GitHub Docs

リポジトリの [Settings] > [Actions] > [Add runner] > [Configure] に表示されるコマンドを実行する。

Windows
cd runner/_layout/
./config.cmd --url https://github.com/[USER_NAME]/[REPOSITORY_NAME] --token ***
./run.cmd
`config.cmd` を実行するときに色々聞かれるので入力する
> .\config.cmd --url https://github.com/SnowCait/sandbox --token ***

--------------------------------------------------------------------------------
|        ____ _ _   _   _       _          _        _   _                      |
|       / ___(_) |_| | | |_   _| |__      / \   ___| |_(_) ___  _ __  ___      |
|      | |  _| | __| |_| | | | | '_ \    / _ \ / __| __| |/ _ \| '_ \/ __|     |
|      | |_| | | |_|  _  | |_| | |_) |  / ___ \ (__| |_| | (_) | | | \__ \     |
|       \____|_|\__|_| |_|\__,_|_.__/  /_/   \_\___|\__|_|\___/|_| |_|___/     |
|                                                                              |
|                       Self-hosted runner registration                        |
|                                                                              |
--------------------------------------------------------------------------------

# Authentication


√ Connected to GitHub

# Runner Registration


This runner will have the following labels: 'self-hosted', 'Windows', 'X64' 
Enter any additional labels (ex. label-1,label-2): [press Enter to skip] 

√ Runner successfully added
√ Runner connection is good

# Runner settings

Enter name of work folder: [press Enter for _work]

√ Settings Saved.

Would you like to run the runner as service? (Y/N) [press Enter for N]

ログ

セルフホストランナーのモニタリングとトラブルシューティング - GitHub Docs

_layout/_diag/ がログディレクトリ。
Runner_* : アプリケーション (config.cmdrun.cmd) が起動される度に生成される。
Worker_* : ジョブ毎に生成される。

ワークフロー

.github/workflows/ci.yml
name: CI

on:
  push:
    branches: [ main ]
    workflow_dispatch:

jobs:
  build:
    runs-on: [self-hosted, Windows]
    defaults:
      run:
        shell: cmd # PowerShell は権限を変更する必要がある

    steps:
      - uses: actions/checkout@v2
      - run: dir

ワークスペース

_diag/_work/[REPOSITORY_NAME]/[REPOSITORY_NAME]/

停止&解除

Ctrl + C で停止します。
リポジトリの登録を解除するには以下のコマンドを実行します。
token は登録時と異なる解除用のもののようです。

./config.cmd remove --token ***
雪猫雪猫

コードを読む

実行ファイルは config.cmdrun.cmd の 2 つ。

ビルドで生成されたコード

config.cmd
@echo off

rem ********************************************************************************
rem Unblock specific files.
rem ********************************************************************************
setlocal
if defined VERBOSE_ARG (
  set VERBOSE_ARG='Continue'
) else (
  set VERBOSE_ARG='SilentlyContinue'
)

rem Unblock files in the root of the layout folder. E.g. .cmd files.
powershell.exe -NoLogo -Sta -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command "$VerbosePreference = %VERBOSE_ARG% ; Get-ChildItem -LiteralPath '%~dp0' | ForEach-Object { Write-Verbose ('Unblock: {0}' -f $_.FullName) ; $_ } | Unblock-File | Out-Null"

if /i "%~1" equ "remove" (
    rem ********************************************************************************
    rem Unconfigure the runner.
    rem ********************************************************************************
    "%~dp0bin\Runner.Listener.exe" %*
) else (
    rem ********************************************************************************
    rem Configure the runner.
    rem ********************************************************************************
    "%~dp0bin\Runner.Listener.exe" configure %*
)
run.cmd
@echo off

rem ********************************************************************************
rem Unblock specific files.
rem ********************************************************************************
setlocal
if defined VERBOSE_ARG (
  set VERBOSE_ARG='Continue'
) else (
  set VERBOSE_ARG='SilentlyContinue'
)

rem Unblock files in the root of the layout folder. E.g. .cmd files.
powershell.exe -NoLogo -Sta -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command "$VerbosePreference = %VERBOSE_ARG% ; Get-ChildItem -LiteralPath '%~dp0' | ForEach-Object { Write-Verbose ('Unblock: {0}' -f $_.FullName) ; $_ } | Unblock-File | Out-Null"

if /i "%~1" equ "localRun" (
    rem ********************************************************************************
    rem Local run.
    rem ********************************************************************************
    "%~dp0bin\Runner.Listener.exe" %*
) else (
  rem ********************************************************************************
  rem Run.
  rem ********************************************************************************
  "%~dp0bin\Runner.Listener.exe" run %*

  rem Return code 4 means the run once runner received an update message.
  rem Sleep 5 seconds to wait for the update process finish and run the runner again.
  if ERRORLEVEL 4 (
    timeout /t 5 /nobreak > NUL
    "%~dp0bin\Runner.Listener.exe" run %*
  )
)

雪猫雪猫

config.cmd

Runner.Listener.exe が本体のようです。
runner/src/Runner.ListenerProgram.cs から読んでいきましょう。

Program.Main

Program.cs
namespace GitHub.Runner.Listener
{
    public static class Program
    {
        public static int Main(string[] args)
        {
            // Add environment variables from .env file
            LoadAndSetEnv();

            using (HostContext context = new HostContext("Runner"))
            {
                return MainAsync(context, args).GetAwaiter().GetResult();
            }
        }
    }
}

.env ファイルはないので LoadAndSetEnv() は無視します。

Program.MainAsync

MainAsync へ。

trace.Info()Runner_* へログを出力しているようです。

Tracing trace = context.GetTrace(nameof(GitHub.Runner.Listener));
trace.Info($"Runner is built for {Constants.Runner.Platform} ({Constants.Runner.PlatformArchitecture}) - {BuildConstants.RunnerPackage.PackageName}.");

コマンドライン引数を受け取ります。
urltoken が渡されているはずです。

// Parse the command line args.
var command = new CommandSettings(context, args);

おそらくコアクラスであろう Runner を実行します。
実態は Runner.cs でしょうか。

// Defer to the Runner class to execute the command.
IRunner runner = context.GetService<IRunner>();
try
{
    var returnCode = await runner.ExecuteCommand(command);
    trace.Info($"Runner execution has finished with return code {returnCode}");
    return returnCode;
}