Skip to main content

PowerShell ๋นŒ๋“œ ๋ฐ ํ…Œ์ŠคํŠธ

CI(์—ฐ์† ํ†ตํ•ฉ) ์›Œํฌํ”Œ๋กœ๋ฅผ ๋งŒ๋“ค์–ด PowerShell ํ”„๋กœ์ ํŠธ๋ฅผ ๋นŒ๋“œํ•˜๊ณ  ํ…Œ์ŠคํŠธํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์„ธ์š”.

์†Œ๊ฐœ

์ด ๊ฐ€์ด๋“œ์—์„œ๋Š” CI์šฉ PowerShell์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ ์ค๋‹ˆ๋‹ค. Pester๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ์ข…์†์„ฑ์„ ์„ค์น˜ํ•˜๊ณ , ๋ชจ๋“ˆ์„ ํ…Œ์ŠคํŠธํ•˜๊ณ , PowerShell ๊ฐค๋Ÿฌ๋ฆฌ ๊ฒŒ์‹œํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

GitHub ํ˜ธ์ŠคํŠธ ๋Ÿฌ๋„ˆ์—๋Š” PowerShell ๋ฐ Pester๊ฐ€ ํฌํ•จ๋œ ์†Œํ”„ํŠธ์›จ์–ด๊ฐ€ ์‚ฌ์ „ ์„ค์น˜๋œ ๋„๊ตฌ ์บ์‹œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์ตœ์‹  ์†Œํ”„ํŠธ์›จ์–ด ๋ฐ ์‚ฌ์ „ ์„ค์น˜๋œ ๋ฒ„์ „์˜ Python๊ณผ Pester์— ๋Œ€ํ•œ ์ „์ฒด ๋ชฉ๋ก์€ GitHub ํ˜ธ์ŠคํŒ… ์‹คํ–‰๊ธฐ์„(๋ฅผ) ์ฐธ์กฐํ•˜์„ธ์š”.

ํ•„์ˆ˜ ์กฐ๊ฑด

YAML ๋ฐ GitHub Actions์˜ ๊ตฌ๋ฌธ์— ๋Œ€ํ•ด ์ž˜ ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์›Œํฌํ”Œ๋กœ ์ž‘์„ฑ์„(๋ฅผ) ์ฐธ์กฐํ•˜์„ธ์š”.

PowerShell ๋ฐ Pester๋ฅผ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋‹ค์Œ์„ ์ฐธ์กฐํ•˜์„ธ์š”.

Pester์— ๋Œ€ํ•œ ์›Œํฌํ”Œ๋กœ ์ถ”๊ฐ€

PowerShell ๋ฐ Pester๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ…Œ์ŠคํŠธ๋ฅผ ์ž๋™ํ™”ํ•˜๋ ค๋ฉด ๋ณ€๊ฒฝ ๋‚ด์šฉ์ด ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ํ‘ธ์‹œ๋  ๋•Œ๋งˆ๋‹ค ์‹คํ–‰๋˜๋Š” ์›Œํฌํ”Œ๋กœ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ์˜ˆ์ œ์—์„œ Test-Path๋Š” resultsfile.log๋ผ๋Š” ํŒŒ์ผ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

์ด ์˜ˆ์ œ ์›Œํฌํ”Œ๋กœ ํŒŒ์ผ์„ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์˜ .github/workflows/ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

name: Test PowerShell on Ubuntu
on: push

jobs:
  pester-test:
    name: Pester test
    runs-on: ubuntu-latest
    steps:
      - name: Check out repository code
        uses: actions/checkout@v4
      - name: Perform a Pester test from the command-line
        shell: pwsh
        run: Test-Path resultsfile.log | Should -Be $true
      - name: Perform a Pester test from the Tests.ps1 file
        shell: pwsh
        run: |
          Invoke-Pester Unit.Tests.ps1 -Passthru
  • shell: pwsh - run ๋ช…๋ น์„ ์‹คํ–‰ํ•  ๋•Œ PowerShell์„ ์‚ฌ์šฉํ•˜๋„๋ก ์ž‘์—…์„ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.

  • run: Test-Path resultsfile.log - resultsfile.log๋ผ๋Š” ํŒŒ์ผ์ด ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์˜ ๋ฃจํŠธ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

  • Should -Be $true - Pester๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์˜ˆ์ƒ ๊ฒฐ๊ณผ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๊ธฐ์น˜ ์•Š์€ ๊ฒฐ๊ณผ์ธ ๊ฒฝ์šฐ GitHub Actions๋Š” ์ด๋ฅผ ์‹คํŒจํ•œ ํ…Œ์ŠคํŠธ๋กœ ํ”Œ๋ž˜๊ทธ๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ์‹œ:

    Pester ํ…Œ์ŠคํŠธ์— ๋Œ€ํ•œ ์›Œํฌํ”Œ๋กœ ์‹คํ–‰ ์‹คํŒจ์˜ ์Šคํฌ๋ฆฐ์ƒท. ํ…Œ์ŠคํŠธ๋Š” "$true๋ฅผ ์˜ˆ์ƒํ–ˆ์ง€๋งŒ $false๊ฐ€ ๋‚˜์˜ด" ๋ฐ "์˜ค๋ฅ˜: ์ข…๋ฃŒ ์ฝ”๋“œ 1๋กœ ์™„๋ฃŒ๋œ ํ”„๋กœ์„ธ์Šค"๋ฅผ ๋ณด๊ณ ํ•ฉ๋‹ˆ๋‹ค.

  • Invoke-Pester Unit.Tests.ps1 -Passthru - Pester๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Unit.Tests.ps1์ด๋ผ๋Š” ํŒŒ์ผ์— ์ •์˜๋œ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์œ„์—์„œ ์„ค๋ช…ํ•œ ๊ฒƒ๊ณผ ๋™์ผํ•œ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด Unit.Tests.ps1์—๋Š” ๋‹ค์Œ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

    Describe "Check results file is present" {
        It "Check results file is present" {
            Test-Path resultsfile.log | Should -Be $true
        }
    }
    

PowerShell ๋ชจ๋“ˆ ์œ„์น˜

์•„๋ž˜ ํ…Œ์ด๋ธ”์€ ๊ฐ GitHub ํ˜ธ์ŠคํŠธ ๋Ÿฌ๋„ˆ์—์„œ ๋‹ค์–‘ํ•œ PowerShell ๋ชจ๋“ˆ์˜ ์œ„์น˜๋ฅผ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

UbuntumacOSWindows
PowerShell ์‹œ์Šคํ…œ ๋ชจ๋“ˆ/opt/microsoft/powershell/7/Modules/*/usr/local/microsoft/powershell/7/Modules/*C:\program files\powershell\7\Modules\*
PowerShell ์ถ”๊ฐ€ ํ•ญ๋ชฉ ๋ชจ๋“ˆ/usr/local/share/powershell/Modules/*/usr/local/share/powershell/Modules/*C:\Modules\*
์‚ฌ์šฉ์ž๊ฐ€ ์„ค์น˜ํ•œ ๋ชจ๋“ˆ/home/runner/.local/share/powershell/Modules/*/Users/runner/.local/share/powershell/Modules/*C:\Users\runneradmin\Documents\PowerShell\Modules\*

์ฐธ๊ณ  ํ•ญ๋ชฉ

Ubuntu ์‹คํ–‰๊ธฐ์—์„œ Azure PowerShell ๋ชจ๋“ˆ์€ PowerShell ์ถ”๊ฐ€ ๊ธฐ๋Šฅ ๋ชจ๋“ˆ(์˜ˆ: /usr/local/share/powershell/Modules/)์˜ ๊ธฐ๋ณธ ์œ„์น˜ ๋Œ€์‹  /usr/share/์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.

์ข…์†์„ฑ ์„ค์น˜

GitHub ํ˜ธ์ŠคํŠธ ์‹คํ–‰๊ธฐ์—๋Š” PowerShell 7 ๋ฐ Pester๊ฐ€ ์„ค์น˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ๋ฅผ ๋นŒ๋“œํ•˜๊ณ  ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์ „์— Install-Module์„ ์‚ฌ์šฉํ•˜์—ฌ PowerShell ๊ฐค๋Ÿฌ๋ฆฌ์—์„œ ์ถ”๊ฐ€ ์ข…์†์„ฑ์„ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ  ํ•ญ๋ชฉ

GitHub ํ˜ธ์ŠคํŠธ ์‹คํ–‰๊ธฐ๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ์ „ ์„ค์น˜๋œ ํŒจํ‚ค์ง€(์˜ˆ: Pester)๋Š” ์ •๊ธฐ์ ์œผ๋กœ ์—…๋ฐ์ดํŠธ๋˜๋ฉฐ ์ค‘์š”ํ•œ ๋ณ€๊ฒฝ ๋‚ด์šฉ์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ -MaximumVersion๊ณผ ํ•จ๊ป˜ Install-Module์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•ญ์ƒ ํ•„์š”ํ•œ ํŒจํ‚ค์ง€ ๋ฒ„์ „์„ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

์ข…์†์„ฑ์„ ์บ์‹œํ•˜์—ฌ ์›Œํฌํ”Œ๋กœ ์†๋„๋ฅผ ๋†’์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ข…์†์„ฑ ์บ์‹ฑ ์ฐธ์กฐ์„(๋ฅผ) ์ฐธ์กฐํ•˜์„ธ์š”.

์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ ์ž‘์—…์€ SqlServer ๋ฐ PSScriptAnalyzer ๋ชจ๋“ˆ์„ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.

jobs:
  install-dependencies:
    name: Install dependencies
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install from PSGallery
        shell: pwsh
        run: |
          Set-PSRepository PSGallery -InstallationPolicy Trusted
          Install-Module SqlServer, PSScriptAnalyzer

์ฐธ๊ณ  ํ•ญ๋ชฉ

๊ธฐ๋ณธ๊ฐ’์œผ๋กœ PowerShell์€ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ์‹ ๋ขฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. PowerShell ๊ฐค๋Ÿฌ๋ฆฌ์—์„œ ๋ชจ๋“ˆ์„ ์„ค์น˜ํ•  ๋•Œ PSGallery์— ๋Œ€ํ•œ ์„ค์น˜ ์ •์ฑ…์„ Trusted๋กœ ๋ช…์‹œ์ ์œผ๋กœ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ข…์†์„ฑ ์บ์‹ฑ

๊ณ ์œ ํ•œ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ PowerShell ์ข…์†์„ฑ์„ ์บ์‹œํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ cache ์ž‘์—…์œผ๋กœ ํ–ฅํ›„ ์›Œํฌํ”Œ๋กœ์— ๋Œ€ํ•œ ์ข…์†์„ฑ์„ ๋ณต์›ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ข…์†์„ฑ ์บ์‹ฑ ์ฐธ์กฐ์„(๋ฅผ) ์ฐธ์กฐํ•˜์„ธ์š”.

PowerShell์€ ์‹คํ–‰๊ธฐ์˜ ์šด์˜ ์ฒด์ œ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ์œ„์น˜์— ์ข…์†์„ฑ์„ ์บ์‹œํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ Ubuntu ์˜ˆ์ œ์—์„œ ์‚ฌ์šฉ๋œ path ์œ„์น˜๋Š” Windows ์šด์˜ ์ฒด์ œ์—์„œ๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

steps:
  - uses: actions/checkout@v4
  - name: Setup PowerShell module cache
    id: cacher
    uses: actions/cache@v4
    with:
      path: "~/.local/share/powershell/Modules"
      key: ${{ runner.os }}-SqlServer-PSScriptAnalyzer
  - name: Install required PowerShell modules
    if: steps.cacher.outputs.cache-hit != 'true'
    shell: pwsh
    run: |
      Set-PSRepository PSGallery -InstallationPolicy Trusted
      Install-Module SqlServer, PSScriptAnalyzer -ErrorAction Stop

์ฝ”๋“œ ํ…Œ์ŠคํŠธ

์ฝ”๋“œ๋ฅผ ๋นŒ๋“œํ•˜๊ณ  ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์œ„ํ•ด ๋กœ์ปฌ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ๋ช…๋ น์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

PSScriptAnalyzer๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฝ”๋“œ ๋ฆฐํŠธ

๋‹ค์Œ ์˜ˆ์ œ์—์„œ๋Š” PSScriptAnalyzer๋ฅผ ์„ค์น˜ํ•˜๊ณ  ์ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์˜ ๋ชจ๋“  ps1 ํŒŒ์ผ์„ ๋ฆฐํŠธํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ GitHub์˜ PSScriptAnalyzer๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

  lint-with-PSScriptAnalyzer:
    name: Install and run PSScriptAnalyzer
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install PSScriptAnalyzer module
        shell: pwsh
        run: |
          Set-PSRepository PSGallery -InstallationPolicy Trusted
          Install-Module PSScriptAnalyzer -ErrorAction Stop
      - name: Lint with PSScriptAnalyzer
        shell: pwsh
        run: |
          Invoke-ScriptAnalyzer -Path *.ps1 -Recurse -Outvariable issues
          $errors   = $issues.Where({$_.Severity -eq 'Error'})
          $warnings = $issues.Where({$_.Severity -eq 'Warning'})
          if ($errors) {
              Write-Error "There were $($errors.Count) errors and $($warnings.Count) warnings total." -ErrorAction Stop
          } else {
              Write-Output "There were $($errors.Count) errors and $($warnings.Count) warnings total."
          }

์›Œํฌํ”Œ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์•„ํ‹ฐํŒฉํŠธ๋กœ ํŒจํ‚ค์ง€

์›Œํฌํ”Œ๋กœ๊ฐ€ ์™„๋ฃŒ๋œ ํ›„ ๋ณผ ์•„ํ‹ฐํŒฉํŠธ๋ฅผ ์—…๋กœ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋กœ๊ทธ ํŒŒ์ผ, ์ฝ”์–ด ๋คํ”„, ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ ๋˜๋Š” ์Šคํฌ๋ฆฐ์ƒท์„ ์ €์žฅํ•ด์•ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์›Œํฌํ”Œ๋กœ ์•„ํ‹ฐํŒฉํŠธ์™€ ๋ฐ์ดํ„ฐ ์ €์žฅ ๋ฐ ๊ณต์œ ์„(๋ฅผ) ์ฐธ์กฐํ•˜์„ธ์š”.

๋‹ค์Œ ์˜ˆ์ œ์—์„œ๋Š” upload-artifact ์ž‘์—…์„ ์‚ฌ์šฉํ•˜์—ฌ Invoke-Pester์—์„œ ๋ฐ›์€ ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ด€ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ ์ค๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ upload-artifact ์ž‘์—…์„ ์ฐธ์กฐํ•˜์„ธ์š”.

name: Upload artifact from Ubuntu

on: [push]

jobs:
  upload-pester-results:
    name: Run Pester and upload results
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Test with Pester
        shell: pwsh
        run: Invoke-Pester Unit.Tests.ps1 -Passthru | Export-CliXml -Path Unit.Tests.xml
      - name: Upload test results
        uses: actions/upload-artifact@v4
        with:
          name: ubuntu-Unit-Tests
          path: Unit.Tests.xml
    if: ${{ always() }}

always() ํ•จ์ˆ˜๋Š” ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํŒจํ•˜๋”๋ผ๋„ ๊ณ„์† ์ฒ˜๋ฆฌํ•˜๋„๋ก ์ž‘์—…์„ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ปจํ…์ŠคํŠธ ์ฐธ์กฐ์„(๋ฅผ) ์ฐธ์กฐํ•˜์„ธ์š”.

CI ํ…Œ์ŠคํŠธ์— ํ†ต๊ณผํ•˜๋ฉด PowerShell ๋ชจ๋“ˆ์„ PowerShell ๊ฐค๋Ÿฌ๋ฆฌ ๊ฒŒ์‹œํ•˜๋„๋ก ์›Œํฌํ”Œ๋กœ๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋น„๋ฐ€์„ ์‚ฌ์šฉํ•˜์—ฌ ํŒจํ‚ค์ง€๋ฅผ ๊ฒŒ์‹œํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ชจ๋“  ํ† ํฐ ๋˜๋Š” ์ž๊ฒฉ ์ฆ๋ช…์„ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ GitHub Actions์—์„œ ๋น„๋ฐ€ ์‚ฌ์šฉ์„(๋ฅผ) ์ฐธ์กฐํ•˜์„ธ์š”.

๋‹ค์Œ ์˜ˆ์ œ์—์„œ๋Š” ํŒจํ‚ค์ง€๋ฅผ ๋งŒ๋“ค๊ณ  Publish-Module์„ ์‚ฌ์šฉํ•˜์—ฌ PowerShell ๊ฐค๋Ÿฌ๋ฆฌ์— ๊ฒŒ์‹œํ•ฉ๋‹ˆ๋‹ค.

name: Publish PowerShell Module

on:
  release:
    types: [created]

jobs:
  publish-to-gallery:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build and publish
        env:
          NUGET_KEY: ${{ secrets.NUGET_KEY }}
        shell: pwsh
        run: |
          ./build.ps1 -Path /tmp/samplemodule
          Publish-Module -Path /tmp/samplemodule -NuGetApiKey $env:NUGET_KEY -Verbose