Polish Multi-CLI v1 release surface #26
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [main, master] | |
| pull_request: | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ci-${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| install-smoke: | |
| name: install + run (${{ matrix.os }}) | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 20 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest] | |
| steps: | |
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 | |
| - name: Remove pre-installed jq so the installer must provide it | |
| run: | | |
| if command -v apt-get >/dev/null 2>&1; then | |
| sudo apt-get remove -y jq || true | |
| elif command -v brew >/dev/null 2>&1; then | |
| brew uninstall --ignore-dependencies --force jq || true | |
| fi | |
| hash -r | |
| if command -v jq >/dev/null 2>&1; then | |
| echo "WARNING: jq still present at $(command -v jq); installer will detect-and-skip." | |
| else | |
| echo "jq removed; installer must reinstall it." | |
| fi | |
| - name: Install multi-cli from the working tree | |
| run: bash scripts/install.sh --local | |
| - name: jq is available after install | |
| run: | | |
| command -v jq | |
| jq --version | |
| - name: doctor / tools / new must all exit 0 | |
| run: | | |
| export PATH="$HOME/.local/bin:$PATH" | |
| multi-cli doctor | |
| multi-cli tools | |
| multi-cli new codex/ciprofile | |
| shellcheck: | |
| name: shellcheck | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 | |
| - name: Install shellcheck | |
| run: sudo apt-get update -y && sudo apt-get install -y shellcheck | |
| - name: Lint shell scripts | |
| run: shellcheck --severity=error multi-cli scripts/install.sh scripts/uninstall.sh scripts/release-build.sh | |
| pwsh-lint: | |
| name: PSScriptAnalyzer | |
| runs-on: windows-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 | |
| - name: Install PSScriptAnalyzer | |
| shell: pwsh | |
| run: | | |
| Set-PSRepository -Name PSGallery -InstallationPolicy Trusted | |
| Install-Module -Name PSScriptAnalyzer -Force -Scope CurrentUser | |
| - name: Analyze PowerShell scripts | |
| shell: pwsh | |
| run: | | |
| $targets = @( | |
| 'scripts/install.ps1', | |
| 'scripts/uninstall.ps1', | |
| 'scripts/release-build.ps1', | |
| 'multi-cli.ps1' | |
| ) | |
| $excludedRules = @( | |
| 'PSAvoidUsingConvertToSecureStringWithPlainText', | |
| 'PSUseShouldProcessForStateChangingFunctions' | |
| ) | |
| $findings = foreach ($target in $targets) { | |
| Invoke-ScriptAnalyzer -Path $target -Severity Error -ExcludeRule $excludedRules | |
| } | |
| if ($findings) { | |
| $findings | Format-Table -AutoSize | Out-String | Write-Host | |
| throw "PSScriptAnalyzer reported $($findings.Count) error-severity finding(s)." | |
| } | |
| Write-Host "No error-severity findings." | |
| bats: | |
| name: bats (${{ matrix.os }}) | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 45 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest] | |
| steps: | |
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 | |
| - name: Install bats + jq | |
| run: | | |
| if command -v apt-get >/dev/null 2>&1; then | |
| sudo apt-get update -y | |
| sudo apt-get install -y bats jq libsecret-tools gnome-keyring dbus-x11 acl | |
| elif command -v brew >/dev/null 2>&1; then | |
| brew install bats-core jq | |
| else | |
| echo "no supported package manager (apt-get/brew) on this runner" >&2 | |
| exit 1 | |
| fi | |
| bats --version | |
| jq --version | |
| - name: Validate adapter contracts | |
| run: bash scripts/validate-adapters.sh | |
| - name: Prepare an ephemeral CI keychain (macOS) | |
| if: runner.os == 'macOS' | |
| run: | | |
| KEYCHAIN="multicli-ci-$(uuidgen).keychain" | |
| KEYCHAIN_PASSWORD="multicli-ci" | |
| PREVIOUS_DEFAULT="$(security default-keychain -d user | tr -d '"' | xargs)" | |
| echo "MULTICLI_CI_KEYCHAIN=$KEYCHAIN" >> "$GITHUB_ENV" | |
| echo "MULTICLI_PREVIOUS_DEFAULT_KEYCHAIN=$PREVIOUS_DEFAULT" >> "$GITHUB_ENV" | |
| security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN" | |
| security set-keychain-settings -lut 21600 "$KEYCHAIN" | |
| security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN" | |
| security default-keychain -d user -s "$KEYCHAIN" | |
| # shellcheck disable=SC2046 | |
| security list-keychains -d user -s "$KEYCHAIN" $(security list-keychains -d user | tr -d '"') | |
| - name: Run the bats suite | |
| run: | | |
| if [ "$(uname -s)" = "Linux" ]; then | |
| dbus-run-session -- bash -c ' | |
| set -euo pipefail | |
| printf "\n" | gnome-keyring-daemon --unlock --components=secrets >/dev/null | |
| printf "ci-smoke" | secret-tool store --label=ci-smoke service multicli-ci target smoke | |
| [ "$(secret-tool lookup service multicli-ci target smoke)" = "ci-smoke" ] | |
| secret-tool clear service multicli-ci target smoke | |
| exec bash tests/run-bats.sh | |
| ' | |
| else | |
| env MULTICLI_MACOS_KEYCHAIN="$HOME/Library/Keychains/$MULTICLI_CI_KEYCHAIN-db" bash tests/run-bats.sh | |
| fi | |
| - name: Remove the ephemeral CI keychain (macOS) | |
| if: runner.os == 'macOS' && always() | |
| run: | | |
| if [ -n "${MULTICLI_PREVIOUS_DEFAULT_KEYCHAIN:-}" ]; then | |
| security default-keychain -d user -s "$MULTICLI_PREVIOUS_DEFAULT_KEYCHAIN" | |
| fi | |
| if [ -n "${MULTICLI_CI_KEYCHAIN:-}" ]; then | |
| security delete-keychain "$MULTICLI_CI_KEYCHAIN" | |
| fi | |
| bash-coverage: | |
| name: bash coverage (ubuntu-latest) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 | |
| with: | |
| fetch-depth: 2 | |
| - name: Install coverage dependencies | |
| run: | | |
| BASHCOV_VERSION=3.3.0 | |
| BASHCOV_SHA256=9a761b6e36598f74897ead922cc04f85de3d1362f54a595c8eb6fcf5cb139c31 | |
| BASHCOV_GEM="$RUNNER_TEMP/bashcov.gem" | |
| SIMPLECOV_VERSION=0.22.0 | |
| SIMPLECOV_SHA256=fe2622c7834ff23b98066bb0a854284b2729a569ac659f82621fc22ef36213a5 | |
| SIMPLECOV_GEM="$RUNNER_TEMP/simplecov.gem" | |
| sudo apt-get update -y | |
| sudo apt-get install -y bats jq libsecret-tools gnome-keyring dbus-x11 acl ruby | |
| curl -fsSL "https://rubygems.org/gems/bashcov-$BASHCOV_VERSION.gem" -o "$BASHCOV_GEM" | |
| curl -fsSL "https://rubygems.org/gems/simplecov-$SIMPLECOV_VERSION.gem" -o "$SIMPLECOV_GEM" | |
| printf '%s %s\n' "$BASHCOV_SHA256" "$BASHCOV_GEM" | sha256sum --check --strict | |
| printf '%s %s\n' "$SIMPLECOV_SHA256" "$SIMPLECOV_GEM" | sha256sum --check --strict | |
| sudo gem install "$SIMPLECOV_GEM" --no-document | |
| sudo gem install --local "$BASHCOV_GEM" --no-document | |
| bashcov --version | |
| - name: Enforce Bash coverage | |
| env: | |
| COVERAGE_BASELINE: ${{ github.event.pull_request.base.sha || github.event.before || 'HEAD^' }} | |
| run: | | |
| dbus-run-session -- bash -c ' | |
| set -euo pipefail | |
| printf "\n" | gnome-keyring-daemon --unlock --components=secrets >/dev/null | |
| exec env COVERAGE_BASELINE="$COVERAGE_BASELINE" bash tests/coverage/run-bash-coverage.sh | |
| ' | |
| pester: | |
| name: pester (windows-latest) | |
| runs-on: windows-latest | |
| timeout-minutes: 45 | |
| steps: | |
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 | |
| with: | |
| fetch-depth: 2 | |
| - name: Install Pester 3.4.0 (matches the 3.x-compatible suite) | |
| shell: powershell | |
| run: | | |
| Set-PSRepository -Name PSGallery -InstallationPolicy Trusted | |
| Install-PackageProvider -Name NuGet -Force -Scope CurrentUser | |
| Install-Module -Name Pester -RequiredVersion 3.4.0 -Force -SkipPublisherCheck -Scope CurrentUser | |
| - name: Validate adapter contracts | |
| shell: powershell | |
| run: powershell -NoProfile -ExecutionPolicy Bypass -File scripts/Validate-Adapters.ps1 | |
| - name: Run the Pester suite | |
| timeout-minutes: 30 | |
| shell: powershell | |
| run: powershell -NoProfile -ExecutionPolicy Bypass -File tests/run-pester.ps1 -CI | |
| - name: Enforce PowerShell module coverage | |
| shell: powershell | |
| env: | |
| COVERAGE_BASELINE: ${{ github.event.pull_request.base.sha || github.event.before || 'HEAD^' }} | |
| run: powershell -NoProfile -ExecutionPolicy Bypass -File tests/coverage/Invoke-ModuleCoverage.ps1 -MinimumPercent 95 | |
| windows-install-smoke: | |
| name: install + run (windows-latest) | |
| runs-on: windows-latest | |
| timeout-minutes: 20 | |
| steps: | |
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 | |
| - name: Install from working tree | |
| shell: powershell | |
| run: powershell -NoProfile -ExecutionPolicy Bypass -File scripts/install.ps1 -Local | |
| - name: Validate installed launcher | |
| shell: powershell | |
| run: | | |
| powershell -NoProfile -ExecutionPolicy Bypass -File multi-cli.ps1 doctor | |
| powershell -NoProfile -ExecutionPolicy Bypass -File multi-cli.ps1 tools | |
| release-metadata: | |
| name: release metadata | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 | |
| - name: Verify embedded versions | |
| run: | | |
| bash scripts/release-build.sh --check | |
| pwsh -NoProfile -File scripts/release-build.ps1 -Check | |
| python3 scripts/validate-docs.py |