瀏覽代碼

Rewrote CI to Pascal (#5)

Artem V. Ageev 11 月之前
父節點
當前提交
431129d4fa

+ 0 - 7
.github/workflows/make.json

@@ -1,7 +0,0 @@
-{
-    "app" : "QRCodeGenLib",
-    "lib" : "QRCodeGenLib",
-    "tst" : "QRCodeGenLib.Demo/FreePascal.Demo/QrCodeGeneratorDemo.lpi",
-    "pkg" : [
-    ]
-}

+ 183 - 0
.github/workflows/make.pas

@@ -0,0 +1,183 @@
+program Make;
+{$mode objfpc}{$H+}
+
+uses
+  Classes,
+  SysUtils,
+  StrUtils,
+  FileUtil,
+  Zipper,
+  fphttpclient,
+  RegExpr,
+  openssl,
+  opensslsockets,
+  Process;
+
+const
+  Target: string = 'QRCodeGenLib.Demo';
+  Dependencies: array of string = ();
+
+type
+  TLog = (audit, info, error);
+
+  Output = record
+    Success: boolean;
+    Output: string;
+  end;
+
+  procedure OutLog(const Knd: TLog; const Msg: string);
+  begin
+    case Knd of
+      error: Writeln(stderr, #27'[31m', Msg, #27'[0m');
+      info: Writeln(stderr, #27'[32m', Msg, #27'[0m');
+      audit: Writeln(stderr, #27'[33m', Msg, #27'[0m');
+    end;
+  end;
+
+  function CheckModules: string;
+  begin
+    if FileExists('.gitmodules') then
+      if RunCommand('git', ['submodule', 'update', '--init', '--recursive',
+        '--force', '--remote'], Result) then
+        OutLog(info, Result)
+      else
+        OutLog(error, Result);
+  end;
+
+  function AddPackage(const Path: string): string;
+  begin
+    if RunCommand('lazbuild', ['--add-package-link', Path], Result) then
+       OutLog(audit, 'Add package:'#9 + Path);
+  end;
+
+  function SelectString(const Input, Reg: string): string;
+  var
+    Line: string;
+  begin
+    Result := ' ';
+    for Line in Input.Split(LineEnding) do
+      with TRegExpr.Create do
+      begin
+        Expression := Reg;
+        if Exec(Line) then
+          Result += Line + LineEnding;
+        Free;
+      end;
+  end;
+
+  function RunTest(const Path: String): string;
+  begin
+    OutLog(audit, #9'run:'#9 + Path);
+    if RunCommand(Path, ['--all', '--format=plain'], Result) then
+      OutLog(info, #9'success!')
+    else
+      ExitCode += 1;
+    OutLog(audit, Result);
+  end;
+
+  function BuildProject(const Path: string): Output;
+  begin
+    OutLog(audit, 'Build from:'#9 + Path);
+    Result.Success := RunCommand('lazbuild',
+      ['--build-all', '--recursive', '--no-write-project', Path], Result.Output);
+    Result.Output := SelectString(Result.Output, '(Fatal:|Error:|Linking)');
+    if Result.Success then
+    begin
+      Result.Output := Result.Output.Split(' ')[3].Replace(LineEnding, '');
+      OutLog(info, #9'to:'#9 + Result.Output);
+      if ContainsStr(ReadFileToString(Path.Replace('.lpi', '.lpr')), 'consoletestrunner') then
+        RunTest(Result.Output.Replace(#10, ''));
+    end
+    else
+    begin
+      ExitCode += 1;
+      OutLog(error, Result.Output);
+    end;
+  end;
+
+  function DownloadFile(const Uri: string): string;
+  var
+    OutFile: TStream;
+  begin
+    InitSSLInterface;
+    Result := GetTempFileName;
+    OutFile := TFileStream.Create(Result, fmCreate or fmOpenWrite);
+    with TFPHttpClient.Create(nil) do
+    begin
+      try
+        AddHeader('User-Agent', 'Mozilla/5.0 (compatible; fpweb)');
+        AllowRedirect := True;
+        Get(Uri, OutFile);
+        OutLog(audit, 'Download from ' + Uri + ' to ' + Result);
+      finally
+        Free;
+        OutFile.Free;
+      end;
+    end;
+  end;
+
+  procedure UnZip(const ZipFile, ZipPath: string);
+  begin
+    with TUnZipper.Create do
+    begin
+      try
+        FileName := ZipFile;
+        OutputPath := ZipPath;
+        Examine;
+        UnZipAllFiles;
+        OutLog(audit, 'Unzip from'#9 + ZipFile + #9'to'#9 + ZipPath);
+        DeleteFile(ZipFile);
+      finally
+        Free;
+      end;
+    end;
+  end;
+
+  function InstallOPM(const Path: string): string;
+  begin
+    Result :=
+      {$IFDEF MSWINDOWS}
+      GetEnvironmentVariable('APPDATA') + '\.lazarus\onlinepackagemanager\packages\'
+      {$ELSE}
+      GetEnvironmentVariable('HOME') + '/.lazarus/onlinepackagemanager/packages/'
+      {$ENDIF}
+      + Path;
+    if not DirectoryExists(Result) then
+    begin
+      CreateDir(Result);
+      UnZip(DownloadFile('https://packages.lazarus-ide.org/' + Path + '.zip'), Result);
+    end;
+  end;
+
+  function BuildAll: string;
+  var
+    List: TStringList;
+  begin
+    CheckModules;
+    List := FindAllFiles(GetCurrentDir, '*.lpk', True);
+    try
+      for Result in Dependencies do
+        List.AddStrings(FindAllFiles(InstallOPM(Result), '*.lpk', True));
+      for Result in List do
+        AddPackage(Result);
+      List := FindAllFiles(Target, '*.lpi', True);
+      for Result in List do
+        BuildProject(Result);
+    finally
+      List.Free;
+    end;
+    case ExitCode of
+      0: OutLog(info, 'Errors:'#9 + IntToStr(ExitCode));
+      else
+        OutLog(error, 'Errors:'#9 + IntToStr(ExitCode));
+    end;
+  end;
+
+begin
+  try
+    BuildAll
+  except
+    on E: Exception do
+      Writeln(E.ClassName, #9, E.Message);
+  end;
+end.

+ 0 - 187
.github/workflows/make.ps1

@@ -1,187 +0,0 @@
-#!/usr/bin/env pwsh
-##############################################################################################################
-
-Function Show-Usage {
-    "
-vagrant  = 'it-gro/win10-ltsc-eval'
-download = 'https://microsoft.com/en-us/evalcenter'
-package  = 'https://learn.microsoft.com/en-us/mem/configmgr/develop/apps/how-to-create-the-windows-installer-file-msi'
-shell    = 'https://learn.microsoft.com/en-us/powershell'
-
-Usage: pwsh -File $($PSCommandPath) [OPTIONS]
-Options:
-    build
-    lint
-" | Out-Host
-}
-
-Function Build-Project {
-    New-Variable -Option Constant -Name VAR -Value (Get-Content -Path $PSCommandPath.Replace('ps1', 'json') | ConvertFrom-Json)
-    If (! (Test-Path -Path $Var.app)) {
-        "$([char]27)[31m.... $($Var.app) did not find!$([char]27)[0m" | Out-Host
-        Exit 1
-    }
-    If (Test-Path -Path '.gitmodules') {
-        & git submodule update --init --recursive --force --remote | Out-Host
-        "$([char]27)[33m.... [[$($LastExitCode)]] git submodule update$([char]27)[0m" | Out-Host
-    }
-    @(
-        @{
-            Cmd = 'lazbuild'
-            Url = 'https://fossies.org/windows/misc/lazarus-3.6-fpc-3.2.2-win64.exe'
-            Path = "C:\Lazarus"
-        }
-    ) | Where-Object {
-        ! (Test-Path -Path $_.Path)
-    } | ForEach-Object {
-        $_.Url | Request-File | Install-Program
-        $Env:PATH+=";$($_.Path)"
-        Return (Get-Command $_.Cmd).Source
-    } | Out-Host
-    $VAR.Pkg | ForEach-Object {
-        @{
-            Name = $_
-            Uri = "https://packages.lazarus-ide.org/$($_).zip"
-            Path = "$($Env:HOME)\.lazarus\onlinepackagemanager\packages\$($_)"
-            OutFile = (New-TemporaryFile).FullName
-        }
-    } | Where-Object {
-        ! (Test-Path -Path $_.Path) &&
-        ! (& lazbuild --verbose-pkgsearch $_.Name ) &&
-        ! (& lazbuild --add-package $_.Name)
-    } | ForEach-Object -Parallel {
-        Invoke-WebRequest -OutFile $_.OutFile -Uri $_.Uri
-        New-Item -Type Directory -Path $_.Path | Out-Null
-        Expand-Archive -Path $_.OutFile -DestinationPath $_.Path
-        Remove-Item $_.OutFile
-        (Get-ChildItem -Filter '*.lpk' -Recurse -File –Path $_.Path).FullName |
-            ForEach-Object {
-                & lazbuild --add-package-link $_ | Out-Null
-                Return "$([char]27)[33m.... [$($LastExitCode)] add package link $($_)$([char]27)[0m"
-            }
-    } | Out-Host
-    If (Test-Path -Path $VAR.lib) {
-        (Get-ChildItem -Filter '*.lpk' -Recurse -File –Path $VAR.lib).FullName |
-            ForEach-Object {
-                & lazbuild --add-package-link $_ | Out-Null
-                Return "$([char]27)[33m.... [$($LastExitCode)] add package link $($_)$([char]27)[0m"
-            } | Out-Host
-    }
-    Exit $(Switch (Test-Path -Path $Var.tst) {
-        true {
-            $Output = (
-                & lazbuild --build-all --recursive --no-write-project $VAR.tst |
-                    Where-Object {
-                        $_.Contains('Linking')
-                    } | ForEach-Object {
-                        $_.Split(' ')[2].Replace('bin', 'bin\.')
-                    }
-            )
-            $Output = (& $Output --all --format=plain --progress)
-            $exitCode = Switch ($LastExitCode) {
-                0 {0}
-                Default {
-                    1
-                }
-            }
-            $Output | Out-Host
-            Return $exitCode
-K        }
-        Default {0}
-    }) + (
-        (Get-ChildItem -Filter '*.lpi' -Recurse -File –Path $Var.app).FullName |
-            ForEach-Object {
-                $Output = (& lazbuild --build-all --recursive --no-write-project $_)
-                $Result = @("$([char]27)[32m.... [$($LastExitCode)] build project $($_)$([char]27)[0m")
-                $exitCode = $(Switch ($LastExitCode) {
-                    0 {
-                        $Result += $Output | Select-String -Pattern 'Linking'
-                        0
-                    }
-                    Default {
-                        $Result += $Output | Select-String -Pattern 'Error:', 'Fatal:'
-                        1
-                    }
-                })
-                $Result | Out-Host
-                Return $exitCode
-            } | Measure-Object -Sum
-    ).Sum
-}
-
-Function Request-File {
-    While ($Input.MoveNext()) {
-        New-Variable -Option Constant -Name VAR -Value @{
-            Uri = $Input.Current
-            OutFile = (Split-Path -Path $Input.Current -Leaf).Split('?')[0]
-        }
-        Invoke-WebRequest @VAR
-        Return $VAR.OutFile
-    }
-}
-
-Function Install-Program {
-    While ($Input.MoveNext()) {
-        Switch ((Split-Path -Path $Input.Current -Leaf).Split('.')[-1]) {
-            'msi' {
-                & msiexec /passive /package $Input.Current | Out-Null
-            }
-            Default {
-                & ".\$($Input.Current)" /SP- /VERYSILENT /SUPPRESSMSGBOXES /NORESTART | Out-Null
-            }
-        }
-        Remove-Item $Input.Current
-    }
-}
-
-Function Request-URL([Switch] $Post) {
-    $VAR = Switch ($Post) {
-        true {
-            @{
-                Method = 'POST'
-                Headers = @{
-                    ContentType = 'application/json'
-                }
-                Uri = 'https://postman-echo.com/post'
-                Body = @{
-                    One = '1'
-                } | ConvertTo-Json
-            }
-        }
-        false {
-            @{
-                Uri = 'https://postman-echo.com/get'
-            }
-        }
-    }
-    Return (Invoke-WebRequest @VAR | ConvertFrom-Json).Headers
-}
-
-Function Switch-Action {
-    $ErrorActionPreference = 'stop'
-    Set-PSDebug -Strict #-Trace 1
-    Invoke-ScriptAnalyzer -EnableExit -Path $PSCommandPath
-    If ($args.count -gt 0) {
-        Switch ($args[0]) {
-            'lint' {
-                Invoke-ScriptAnalyzer -EnableExit -Recurse -Path '.'
-                (Get-ChildItem -Filter '*.ps1' -Recurse -Path '.').FullName |
-                    ForEach-Object {
-                        Invoke-Formatter -ScriptDefinition $(Get-Content -Path $_ | Out-String) |
-                            Set-Content -Path $_
-                    }
-            }
-            'build' {
-                Build-Project
-            }
-            Default {
-                Show-Usage
-            }
-        }
-    } Else {
-        Show-Usage
-    }
-}
-
-##############################################################################################################
-Switch-Action @args

+ 0 - 112
.github/workflows/make.sh

@@ -1,112 +0,0 @@
-#!/usr/bin/env bash
-##############################################################################################################
-
-function priv_clippit
-(
-    cat <<EOF
-https://google.github.io/styleguide/shellguide.html
-https://guide.bash.academy
-https://devhints.io/bash
-https://tldr.sh
-
-Usage: bash ${0} [OPTIONS]
-Options:
-    build   Build program
-EOF
-)
-
-function priv_lazbuild
-(
-    mapfile -t < "${0//sh/json}"
-    declare -rA VAR=(
-        [app]=$(jq --raw-output --exit-status '.app' <<< "${MAPFILE[@]}")
-        [lib]=$(jq --raw-output --exit-status '.lib' <<< "${MAPFILE[@]}")
-        [tst]=$(jq --raw-output --exit-status '.tst' <<< "${MAPFILE[@]}")
-        [opt]=$(jq --raw-output --exit-status '.opt' <<< "${MAPFILE[@]}")
-    )
-    if ! [[ -d "${VAR[app]}" ]]; then
-        printf '\x1b[32m\t[%s] did not find!\x1b[0m\n' "${VAR[app]}"
-        exit 1
-    fi >&2
-    if [[ -f '.gitmodules' ]]; then
-        git submodule update --init --recursive --force --remote &
-    fi
-    if ! (command -v lazbuild); then
-        # shellcheck source=/dev/null
-        source '/etc/os-release'
-        case ${ID:?} in
-            debian | ubuntu)
-                sudo apt-get update
-                sudo apt-get install -y lazarus{-ide-qt5,} &
-                ;;
-        esac
-    fi &>/dev/null
-    wait
-    while read -r; do
-        (
-            declare -rA TMP=(
-                [url]="https://packages.lazarus-ide.org/${REPLY}.zip"
-                [dir]="${HOME}/.lazarus/onlinepackagemanager/packages/${REPLY}"
-                [out]=$(mktemp)
-            )
-            if ! [[ -d "${TMP[dir]}" ]] &&
-               ! (lazbuild --verbose-pkgsearch "${REPLY}") &&
-               ! (lazbuild --add-package "${REPLY}"); then
-                    wget --quiet --output-document "${TMP[out]}" "${TMP[url]}"
-                    mkdir --parents "${TMP[dir]}"
-                    unzip -o "${TMP[out]}" -d "${TMP[dir]}"
-                    rm --verbose "${TMP[out]}"
-                    find "${TMP[dir]}" -type 'f' -name '*.lpk' -printf '\033[33m\tadd package link\t%p\033[0m\n' -exec \
-                        lazbuild --add-package-link {} + >&2
-            fi
-        ) &
-    done < <(jq --raw-output --exit-status '.pkg[]' <<< "${MAPFILE[@]}")
-    wait
-    if [[ -d "${VAR[lib]}" ]]; then
-        find "${VAR[lib]}" -type 'f' -name '*.lpk' -printf '\033[33m\tadd package link\t%p\033[0m\n' -exec \
-            lazbuild --add-package-link {} + >&2
-    fi
-    declare -i exitCode=0
-    if [[ -f "${VAR[tst]}" ]]; then
-        declare -A TMP=(
-            [tst]=$(
-                lazbuild --build-all --recursive --no-write-project "${VAR[tst]}" |
-                    awk '/Linking/{print $3}'
-            )
-        )
-        if ! ("${TMP[tst]}" --all --format=plain --progress >&2); then
-            ((exitCode+=1))
-        fi
-    fi
-    while read -r; do
-        declare -A TMP=(
-            [out]=$(mktemp)
-        )
-        if (lazbuild --build-all --recursive --no-write-project "${REPLY}" > "${TMP[out]}"); then
-            printf '\x1b[32m\t[%s]\t%s\x1b[0m\n' "${?}" "${REPLY}"
-            grep --color='always' 'Linking' "${TMP[out]}"
-        else
-            printf '\x1b[31m\t[%s]\t%s\x1b[0m\n' "${?}" "${REPLY}"
-            grep --color='always' --extended-regexp '(Error|Fatal):' "${TMP[out]}"
-            ((exitCode+=1))
-        fi >&2
-        rm "${TMP[out]}"
-    done < <(find "${VAR[app]}" -type 'f' -name '*.lpi')
-    exit "${exitCode}"
-)
-
-function priv_main
-(
-    set -euo pipefail
-    if ((${#})); then
-        case ${1} in
-            build) priv_lazbuild ;;
-            *) priv_clippit ;;
-        esac
-    else
-        priv_clippit
-    fi
-)
-
-##############################################################################################################
-priv_main "${@}" >/dev/null

+ 22 - 9
.github/workflows/make.yml

@@ -25,6 +25,7 @@ jobs:
         os:
           - ubuntu-latest
           - windows-latest
+
     steps:
     - name: Checkout
       uses: actions/checkout@v4
@@ -34,16 +35,28 @@ jobs:
     - name: Build on Linux
       if: runner.os == 'Linux'
       shell: bash
-      run: bash .github/workflows/make.sh build
+      run: |
+        set -xeuo pipefail
+        sudo bash -c 'apt-get update; apt-get install -y lazarus' >/dev/null
+        instantfpc -Fu/usr/lib/lazarus/*/components/lazutils \
+          -B '.github/workflows/make.pas'
 
     - name: Build on Windows
       if: runner.os == 'Windows'
       shell: powershell
-      run: pwsh -File .github/workflows/make.ps1 build
-
-    - name: Archive
-      if: runner.os == 'Windows'
-      uses: actions/upload-artifact@v4
-      with:
-        retention-days: 1
-        path: src\bin\*.exe
+      run: |
+        $ErrorActionPreference = 'stop'
+        Set-PSDebug -Strict
+        New-Variable -Option Constant -Name VAR -Value @{
+          Uri =
+            'https://fossies.org/windows/misc/lazarus-3.6-fpc-3.2.2-win64.exe'
+          OutFile = (New-TemporaryFile).FullName + '.exe'
+        }
+        Invoke-WebRequest @VAR
+        & $VAR.OutFile.Replace('Temp', 'Temp\.') /SP- /VERYSILENT /NORESTART `
+          /SUPPRESSMSGBOXES | Out-Null
+        $Env:PATH+=';C:\Lazarus'
+        $Env:PATH+=';C:\Lazarus\fpc\3.2.2\bin\x86_64-win64'
+        'lazbuild', 'instantfpc' | % { (Get-Command $_).Source } | Out-Host
+        instantfpc -FuC:\Lazarus\components\lazutils `
+          -B '.github/workflows/make.pas'

+ 1 - 1
QRCodeGenLib.Demo/FreePascal.Demo/QrCodeGeneratorDemo.lpr

@@ -5,13 +5,13 @@ program QrCodeGeneratorDemo;
 uses {$IFDEF UNIX} {$IFDEF UseCThreads}
   cthreads, {$ENDIF} {$ENDIF}
   SysUtils,
+  consoletestrunner,
   uQrCodeGeneratorDemo;
 
 begin
   try
     { TODO -oUser -cConsole Main : Insert code here }
     TQrCodeGeneratorDemo.RunAllDemos;
-    Readln;
   except
     on E: Exception do
       Writeln(E.ClassName, ': ', E.Message);