1 分钟阅读

最爱PowerShell啦!!!最性感的Shell软件!!!

先展示moment-code的代码层次结构:

  1. Languages
  2. Topics
  3. Projects

我使用PowerShell Core 7对moment-code仓库的构建工作进行自动化。使用根目录的PowerShell脚本build-all.ps1可以调用每一个language下的自定义构建脚本:

function Build-All
{
    param ();

    $language_dir_objects = Get-LanguageDirObjects;
    $language_dirs = $language_dir_objects.Name;

    $built_language_dirs_count = 0;
    foreach ($language_dir in $language_dirs)
    {
        $built_language_dirs_count++;
        Build-LanguageDir $language_dir $built_language_dirs_count $language_dir_objects.Length;

    }
}

function Get-LanguageDirObjects
{
    return (Get-ChildItem -Attributes "directory" | Select-Object -Property "Name");
}

function Build-LanguageDir
{
    param (
        $language_dir,
        $built_language_dirs,
        $total_language_dirs
    );

    Write-Output "---- Building language `"$language_dir`" ($built_language_dirs / $total_language_dirs)";

    $root = (Get-Location).Path;
    if (Test-LanguageBuildingScript $language_dir)
    {
        Set-Location $language_dir;
        ./build.ps1;
        Set-Location $root;
    }
    else 
    {
        Write-Error -Message "Directory `"$language_dir`" doesn't contain build script";
    }

    Set-Location $root;
}


function Test-LanguageBuildingScript
{
    param (
        $language_dir
    );
    $root = (Get-Location).Path;
    Set-Location $language_dir;
    $result = Test-Path -Path "build.ps1";
    Set-Location $root;

    return $result;
}
Build-All;

然后在每一个Language下调用/[lang]/build.ps1build.ps1可以调用每一个topic下的build-topic.ps1,并在缺失build-topic.ps1时发送错误,跳过文件夹。这是C#的build-topic.ps1

# build.ps1
function Test-TopicBuildingScript
{
    param (
        $topic_dir
    );
    $root = (Get-Location).Path;
    Set-Location $topic_dir;
    $result = Test-Path -Path "build-topic.ps1";
    Set-Location $root;

    return $result;
}


$subdirectory_objects = Get-ChildItem -Attributes "directory" | Select-Object -Property "Name"
$subdirectories = $subdirectory_objects.Name;
$count = 1;
foreach ($topic in $subdirectories)
{
    Write-Output "---- Building topic `"$item`" ($count / $($subdirectory_objects.Length)) ...";
    $root = (Get-Location).Path;
    if (Test-TopicBuildingScript $topic)
    {
        Set-Location $topic;
        ./build-topic.ps1;
        Set-Location $root;
    }
    else 
    {
        Write-Error -Message "Error: topic `"$topic`" doesn't contain building script. Skipping...";
    }

    $count++;
}

一个topic下可以包含多个item,说白了就是单个项目,所以对具有统一构建系统(哦~好爽~)的.NET项目来说,如果不需要自己提供构建脚本,那么直接dotnet build就可以了。但是注意:为了节省GitHub Actions的时间,并避免一些莫名其妙的bug,我把dotnet build变成了先dotnet restoredotnet msbuild,并去除logo:--nologo,这样在GitHub Actions上的日志可以很好看(单击截图可以直接前往log页面):

GitHub Action Log

那么,build-topic.ps1在这里(仅指.NET项目的build-topic-ps1):

function Test-ItemBuildingScript
{
    param (
        $item_dir
    );
    $root = (Get-Location).Path;
    Set-Location $item_dir;
    $result = Test-Path -Path "build-item.ps1";
    Set-Location $root;

    return $result;
}

function Test-ProjectFileOrSolutionFile
{
    param (
        $item_dir
    );
    $root = (Get-Location).Path;
    Set-Location $item_dir;
    $result = (Test-Path -Path "*.csproj") -or (Test-Path -Path "*.sln");
    Set-Location $root;

    return $result;
}


$subdirectory_objects = Get-ChildItem -Attributes "directory" | Select-Object -Property "Name"
$subdirectories = $subdirectory_objects.Name;
$count = 1;
foreach ($item in $subdirectories)
{
    Write-Output "---- Building item `"$item`" ($count / $($subdirectory_objects.Length)) ...";
    $root = (Get-Location).Path;
    if (Test-ItemBuildingScript $item)
    {
        Set-Location $item;
        .\build-item.ps1;
        Set-Location $root;
    }
    elseif (Test-ProjectFileOrSolutionFile $item)
    {
        Set-Location $item;
        dotnet restore --nologo;
        dotnet msbuild --nologo;
        Set-Location $root;
    }
    else 
    {
        Write-Error -Message "Error: item `"$item`" contains neither project / solution file nor custom building script. Skipping...";
    }

    $count++;
}

最后,使用对应的ci.yml来配置GitHub Actions,大功告成:

name: Continuous Intergration

on:
  push:
    branches: [ "master" ]
  pull_request:
    branches: [ "master" ]

jobs:
  "Build-CSharp":

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    - name: Set up .NET
      uses: actions/setup-dotnet@v3
      with:
        dotnet-version: 6.0.x
    - name: Build all using PowerShell scripts
      run: pwsh build-all.ps1

这样我就可以在每一次提交时运行CI过程(点击图片可以直接查看所有Actions):

GitHub Actions Screenshot

甚至每一次提交PR都会自动运行状态检查。这是还没有完成检查的界面:

GitHub Actions runs when submitting PR - not completed

这是检查完成后的:

GitHub Actions runs when submitting PR - not completed

分类:

更新时间: