Skip to content

feat: improve command logging with compact format and buffered module… #70

feat: improve command logging with compact format and buffered module…

feat: improve command logging with compact format and buffered module… #70

name: Generate CLI Options

Check failure on line 1 in .github/workflows/generate-cli-options.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/generate-cli-options.yml

Invalid workflow file

you may only define up to 25 `inputs` for a `workflow_dispatch` event
on:
schedule:
# Run every Sunday at 2:00 AM UTC
- cron: '0 2 * * 0'
workflow_dispatch:
inputs:
# Linux tools - Kubernetes/Container ecosystem
helm:
description: 'Helm'
required: false
default: true
type: boolean
kubectl:
description: 'Kubectl'
required: false
default: true
type: boolean
kustomize:
description: 'Kustomize'
required: false
default: true
type: boolean
docker:
description: 'Docker'
required: false
default: true
type: boolean
trivy:
description: 'Trivy (Security Scanner)'
required: false
default: true
type: boolean
hadolint:
description: 'Hadolint (Dockerfile Linter)'
required: false
default: true
type: boolean
podman:
description: 'Podman (Container Engine)'
required: false
default: true
type: boolean
buildah:
description: 'Buildah (Container Builder)'
required: false
default: true
type: boolean
skopeo:
description: 'Skopeo (Container Operations)'
required: false
default: true
type: boolean
# Cloud CLIs
az:
description: 'Azure CLI'
required: false
default: true
type: boolean
gcloud:
description: 'Google Cloud CLI'
required: false
default: true
type: boolean
aws:
description: 'AWS CLI'
required: false
default: true
type: boolean
# Infrastructure/DevOps tools
terraform:
description: 'Terraform'
required: false
default: true
type: boolean
pulumi:
description: 'Pulumi (IaC)'
required: false
default: true
type: boolean
packer:
description: 'Packer (Image Builder)'
required: false
default: true
type: boolean
vault:
description: 'Vault (Secrets Management)'
required: false
default: true
type: boolean
ansible:
description: 'Ansible'
required: false
default: true
type: boolean
flyway:
description: 'Flyway (DB Migrations)'
required: false
default: true
type: boolean
liquibase:
description: 'Liquibase (DB Migrations)'
required: false
default: true
type: boolean
# Development tools
dotnet:
description: '.NET CLI'
required: false
default: true
type: boolean
go:
description: 'Go'
required: false
default: true
type: boolean
cargo:
description: 'Cargo (Rust)'
required: false
default: true
type: boolean
mvn:
description: 'Maven'
required: false
default: true
type: boolean
gradle:
description: 'Gradle'
required: false
default: true
type: boolean
# Node.js ecosystem
yarn:
description: 'Yarn'
required: false
default: true
type: boolean
pnpm:
description: 'pnpm'
required: false
default: true
type: boolean
# GitHub CLI
gh:
description: 'GitHub CLI'
required: false
default: true
type: boolean
# Kubernetes/GitOps
eksctl:
description: 'eksctl (EKS)'
required: false
default: true
type: boolean
argocd:
description: 'ArgoCD'
required: false
default: true
type: boolean
flux:
description: 'Flux (GitOps)'
required: false
default: true
type: boolean
kind:
description: 'Kind (Kubernetes IN Docker)'
required: false
default: true
type: boolean
minikube:
description: 'Minikube (Local Kubernetes)'
required: false
default: true
type: boolean
# Code quality/Security
sonar-scanner:
description: 'SonarScanner'
required: false
default: true
type: boolean
snyk:
description: 'Snyk'
required: false
default: true
type: boolean
shellcheck:
description: 'ShellCheck'
required: false
default: true
type: boolean
# Supply chain security
cosign:
description: 'Cosign (Container Signing)'
required: false
default: true
type: boolean
syft:
description: 'Syft (SBOM Generator)'
required: false
default: true
type: boolean
grype:
description: 'Grype (Vulnerability Scanner)'
required: false
default: true
type: boolean
# Testing
newman:
description: 'Newman (Postman)'
required: false
default: true
type: boolean
# Data processing
jq:
description: 'jq (JSON processor)'
required: false
default: true
type: boolean
yq:
description: 'yq (YAML processor)'
required: false
default: true
type: boolean
# Python
pip:
description: 'pip (Python)'
required: false
default: true
type: boolean
# Windows tools
choco:
description: 'Chocolatey'
required: false
default: true
type: boolean
winget:
description: 'WinGet'
required: false
default: true
type: boolean
# Options
create-pr:
description: 'Create a pull request with changes'
required: false
default: true
type: boolean
jobs:
# Generate options for each tool in parallel (Linux)
generate:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
strategy:
fail-fast: false
matrix:
tool:
# Kubernetes/Container ecosystem
- helm
- kubectl
- kustomize
- docker
- trivy
- hadolint
- podman
- buildah
- skopeo
# Cloud CLIs
- az
- gcloud
- aws
# Infrastructure/DevOps
- terraform
- pulumi
- packer
- vault
- ansible
- flyway
- liquibase
# Development tools
- dotnet
- go
- cargo
- mvn
- gradle
# Node.js ecosystem
- yarn
- pnpm
# GitHub CLI
- gh
# Kubernetes/GitOps
- eksctl
- argocd
- flux
- kind
- minikube
# Code quality/Security
- sonar-scanner
- snyk
- shellcheck
# Supply chain security
- cosign
- syft
- grype
# Testing
- newman
# Data processing
- jq
- yq
# Python
- pip
steps:
- name: Check if tool should run
id: should-run
run: |
# For scheduled runs, all tools run. For manual runs, check the checkbox.
if [[ "${{ github.event_name }}" == "schedule" ]]; then
echo "run=true" >> $GITHUB_OUTPUT
else
# Get the input for this specific tool (defaults to true if not set)
TOOL_ENABLED="${{ github.event.inputs[matrix.tool] }}"
if [[ "$TOOL_ENABLED" != "false" ]]; then
echo "run=true" >> $GITHUB_OUTPUT
else
echo "run=false" >> $GITHUB_OUTPUT
fi
fi
- name: Checkout
if: steps.should-run.outputs.run == 'true'
uses: actions/checkout@v6
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup .NET
if: steps.should-run.outputs.run == 'true'
uses: actions/setup-dotnet@v5
with:
dotnet-version: 10.0.x
- name: Cache NuGet
if: steps.should-run.outputs.run == 'true'
uses: actions/cache@v5
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }}
restore-keys: |
${{ runner.os }}-nuget-
# Clean up legacy manual files before generation
# Only delete specific service interface/implementation files that will be replaced
- name: Clean up legacy files
if: steps.should-run.outputs.run == 'true'
run: |
# Map tool to package directory and namespace prefix
declare -A TOOL_MAP=(
# Kubernetes/Container ecosystem
["helm"]="ModularPipelines.Helm:Helm"
["kubectl"]="ModularPipelines.Kubernetes:Kubernetes"
["kustomize"]="ModularPipelines.Kubernetes:Kustomize"
["docker"]="ModularPipelines.Docker:Docker"
["trivy"]="ModularPipelines.Trivy:Trivy"
["hadolint"]="ModularPipelines.Hadolint:Hadolint"
["podman"]="ModularPipelines.Podman:Podman"
["buildah"]="ModularPipelines.Buildah:Buildah"
["skopeo"]="ModularPipelines.Skopeo:Skopeo"
# Cloud CLIs
["az"]="ModularPipelines.Azure:Az"
["gcloud"]="ModularPipelines.Google:Gcloud"
["aws"]="ModularPipelines.AmazonWebServices:Aws"
# Infrastructure/DevOps
["terraform"]="ModularPipelines.Terraform:Terraform"
["pulumi"]="ModularPipelines.Pulumi:Pulumi"
["packer"]="ModularPipelines.Packer:Packer"
["vault"]="ModularPipelines.Vault:Vault"
["ansible"]="ModularPipelines.Ansible:Ansible"
["flyway"]="ModularPipelines.Flyway:Flyway"
["liquibase"]="ModularPipelines.Liquibase:Liquibase"
# Development tools
["dotnet"]="ModularPipelines.DotNet:DotNet"
["go"]="ModularPipelines.Go:Go"
["cargo"]="ModularPipelines.Rust:Cargo"
["mvn"]="ModularPipelines.Java:Maven"
["gradle"]="ModularPipelines.Java:Gradle"
# Node.js ecosystem
["yarn"]="ModularPipelines.Yarn:Yarn"
["pnpm"]="ModularPipelines.Node:Pnpm"
# GitHub CLI
["gh"]="ModularPipelines.GitHub:Gh"
# Kubernetes/GitOps
["eksctl"]="ModularPipelines.Eksctl:Eksctl"
["argocd"]="ModularPipelines.ArgoCd:ArgoCd"
["flux"]="ModularPipelines.Flux:Flux"
["kind"]="ModularPipelines.Kind:Kind"
["minikube"]="ModularPipelines.Minikube:Minikube"
# Code quality/Security
["sonar-scanner"]="ModularPipelines.SonarScanner:SonarScanner"
["snyk"]="ModularPipelines.Snyk:Snyk"
["shellcheck"]="ModularPipelines.Shellcheck:Shellcheck"
# Supply chain security
["cosign"]="ModularPipelines.Cosign:Cosign"
["syft"]="ModularPipelines.Syft:Syft"
["grype"]="ModularPipelines.Grype:Grype"
# Testing
["newman"]="ModularPipelines.Newman:Newman"
# Data processing
["jq"]="ModularPipelines.Jq:Jq"
["yq"]="ModularPipelines.Yq:Yq"
# Python
["pip"]="ModularPipelines.Python:Pip"
)
IFS=':' read -r PACKAGE PREFIX <<< "${TOOL_MAP[${{ matrix.tool }}]}"
if [ -n "$PACKAGE" ]; then
PKG_DIR="src/$PACKAGE"
if [ -d "$PKG_DIR" ]; then
echo "Cleaning up legacy files in $PKG_DIR for prefix $PREFIX..."
# Only delete specific service interface/implementation files (not all I*.cs files)
# These are the exact files the generator will create in Services/
rm -f "$PKG_DIR/I${PREFIX}.cs" 2>/dev/null || true
rm -f "$PKG_DIR/${PREFIX}.cs" 2>/dev/null || true
# Delete old .Generated.cs files in Services folder (will be replaced with non-.Generated names)
find "$PKG_DIR/Services" -name "*.Generated.cs" -type f -delete 2>/dev/null || true
echo "Cleanup complete for $PACKAGE"
fi
fi
# Install CLI tools needed for CLI-first scraping
- name: Install Helm
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'helm'
run: |
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
- name: Install kubectl
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'kubectl'
run: |
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/
- name: Install Azure CLI
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'az'
run: |
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
- name: Install Google Cloud CLI
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'gcloud'
run: |
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key --keyring /usr/share/keyrings/cloud.google.gpg add -
sudo apt-get update && sudo apt-get install -y google-cloud-cli
- name: Install Terraform
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'terraform'
run: |
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt-get update && sudo apt-get install -y terraform
- name: Install Yarn
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'yarn'
run: |
corepack enable
corepack prepare yarn@stable --activate
- name: Install AWS CLI
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'aws'
run: |
# AWS CLI may be pre-installed on ubuntu-latest, use --update flag
# Install in /tmp to avoid committing installation files
cd /tmp
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip -q awscliv2.zip
sudo ./aws/install --update
cd -
- name: Install Kustomize
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'kustomize'
run: |
curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
sudo mv kustomize /usr/local/bin/
- name: Install Trivy
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'trivy'
run: |
sudo apt-get install -y wget apt-transport-https gnupg lsb-release
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | gpg --dearmor | sudo tee /usr/share/keyrings/trivy.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | sudo tee -a /etc/apt/sources.list.d/trivy.list
sudo apt-get update
sudo apt-get install -y trivy
- name: Install Hadolint
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'hadolint'
run: |
wget -O hadolint https://github.com/hadolint/hadolint/releases/latest/download/hadolint-Linux-x86_64
chmod +x hadolint
sudo mv hadolint /usr/local/bin/
- name: Install Flyway
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'flyway'
run: |
wget -qO- https://download.red-gate.com/maven/release/com/redgate/flyway/flyway-commandline/10.20.1/flyway-commandline-10.20.1-linux-x64.tar.gz | tar xvz
sudo ln -s "$(pwd)/flyway-10.20.1/flyway" /usr/local/bin/flyway
- name: Install Go
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'go'
uses: actions/setup-go@v6
with:
go-version: 'stable'
- name: Install Maven
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'mvn'
run: |
sudo apt-get update
sudo apt-get install -y maven
- name: Install Gradle
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'gradle'
uses: gradle/actions/setup-gradle@v5
- name: Install pnpm
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'pnpm'
run: |
corepack enable
corepack prepare pnpm@latest --activate
- name: Install GitHub CLI
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'gh'
run: |
# GitHub CLI is pre-installed on ubuntu-latest
gh --version
- name: Install SonarScanner
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'sonar-scanner'
run: |
wget -qO- https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-6.2.1.4610-linux-x64.zip -O sonar-scanner.zip
unzip -q sonar-scanner.zip
sudo mv sonar-scanner-6.2.1.4610-linux-x64 /opt/sonar-scanner
sudo ln -s /opt/sonar-scanner/bin/sonar-scanner /usr/local/bin/sonar-scanner
- name: Install Snyk
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'snyk'
run: |
npm install -g snyk
- name: Install jq
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'jq'
run: |
# jq is pre-installed on ubuntu-latest
jq --version
- name: Install yq
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'yq'
run: |
wget -qO /tmp/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
chmod +x /tmp/yq
sudo mv /tmp/yq /usr/local/bin/yq
# Container tools (Docker alternatives)
- name: Install Podman
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'podman'
run: |
sudo apt-get update
sudo apt-get install -y podman
- name: Install Buildah
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'buildah'
run: |
sudo apt-get update
sudo apt-get install -y buildah
- name: Install Skopeo
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'skopeo'
run: |
sudo apt-get update
sudo apt-get install -y skopeo
# Infrastructure as Code tools
- name: Install Pulumi
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'pulumi'
run: |
curl -fsSL https://get.pulumi.com | sh
echo "$HOME/.pulumi/bin" >> $GITHUB_PATH
- name: Install Packer
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'packer'
run: |
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt-get update && sudo apt-get install -y packer
- name: Install Vault
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'vault'
run: |
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt-get update && sudo apt-get install -y vault
- name: Install Ansible
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'ansible'
run: |
sudo apt-get update
sudo apt-get install -y ansible
- name: Install Liquibase
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'liquibase'
run: |
wget -qO- https://github.com/liquibase/liquibase/releases/download/v4.29.2/liquibase-4.29.2.tar.gz | tar xvz -C /tmp
sudo mv /tmp/liquibase /usr/local/bin/
# Rust ecosystem
- name: Install Cargo
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'cargo'
run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
# Kubernetes/GitOps tools
- name: Install eksctl
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'eksctl'
run: |
ARCH=amd64
PLATFORM=$(uname -s)_$ARCH
curl -sLO "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_$PLATFORM.tar.gz"
tar -xzf eksctl_$PLATFORM.tar.gz -C /tmp
sudo mv /tmp/eksctl /usr/local/bin
- name: Install ArgoCD CLI
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'argocd'
run: |
curl -sSL -o /tmp/argocd-linux-amd64 https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
chmod +x /tmp/argocd-linux-amd64
sudo mv /tmp/argocd-linux-amd64 /usr/local/bin/argocd
- name: Install Flux CLI
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'flux'
run: |
curl -s https://fluxcd.io/install.sh | sudo bash
# Local Kubernetes tools
- name: Install Kind
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'kind'
run: |
curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind
- name: Install Minikube
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'minikube'
run: |
curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
chmod +x minikube
sudo mv minikube /usr/local/bin/
# Supply chain security tools
- name: Install Cosign
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'cosign'
run: |
curl -Lo cosign https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64
chmod +x cosign
sudo mv cosign /usr/local/bin/
- name: Install Syft
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'syft'
run: |
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
- name: Install Grype
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'grype'
run: |
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
# Code quality tools
- name: Install ShellCheck
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'shellcheck'
run: |
# ShellCheck is pre-installed on ubuntu-latest
shellcheck --version
# Testing tools
- name: Install Newman
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'newman'
run: |
npm install -g newman
# Docker is pre-installed on ubuntu-latest
# .NET CLI is installed via setup-dotnet
# pip is pre-installed with Python on ubuntu-latest
- name: Build Generator
if: steps.should-run.outputs.run == 'true'
run: dotnet build -c Release
working-directory: tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator
- name: Run Generator for ${{ matrix.tool }}
if: steps.should-run.outputs.run == 'true'
run: |
dotnet run -c Release -- \
--tools "${{ matrix.tool }}" \
--output-dir "${{ github.workspace }}"
working-directory: tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator
- name: Check for changes
if: steps.should-run.outputs.run == 'true'
id: changes
run: |
git add -A
if git diff --staged --quiet; then
echo "has_changes=false" >> $GITHUB_OUTPUT
else
echo "has_changes=true" >> $GITHUB_OUTPUT
echo "Changed files:"
git diff --staged --name-only
fi
- name: Build solution to verify changes
if: steps.should-run.outputs.run == 'true' && steps.changes.outputs.has_changes == 'true'
run: dotnet build ModularPipelines.sln -c Release
- name: Create Pull Request for ${{ matrix.tool }}
id: create-pr
if: steps.should-run.outputs.run == 'true' && steps.changes.outputs.has_changes == 'true' && (github.event.inputs.create-pr != 'false')
uses: peter-evans/create-pull-request@v8
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: "chore: Update ${{ matrix.tool }} CLI options"
title: "[Automated] Update ${{ matrix.tool }} CLI Options"
body: |
## Summary
This PR contains automatically generated updates to **${{ matrix.tool }}** CLI options classes.
The generator scraped the latest CLI help output from the installed tool.
## Changes
- Updated options classes to reflect latest CLI documentation
- Added new commands if any were detected
- Updated option types and descriptions
## Verification
- [x] Solution builds successfully
---
🤖 Generated with ModularPipelines.OptionsGenerator
branch: automated/update-cli-options-${{ matrix.tool }}
base: main
delete-branch: true
labels: |
automated
dependencies
- name: Enable auto-merge
if: steps.create-pr.outputs.pull-request-number
run: gh pr merge ${{ steps.create-pr.outputs.pull-request-number }} --auto --squash
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Generate options for Windows-only tools
generate-windows:
runs-on: windows-latest
permissions:
contents: write
pull-requests: write
strategy:
fail-fast: false
matrix:
tool:
- choco
- winget
steps:
- name: Check if tool should run
id: should-run
shell: pwsh
run: |
# For scheduled runs, all tools run. For manual runs, check the checkbox.
if ("${{ github.event_name }}" -eq "schedule") {
"run=true" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
} else {
# Get the input for this specific tool (defaults to true if not set)
$toolEnabled = "${{ github.event.inputs[matrix.tool] }}"
if ($toolEnabled -ne "false") {
"run=true" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
} else {
"run=false" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
}
}
- name: Checkout
if: steps.should-run.outputs.run == 'true'
uses: actions/checkout@v6
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup .NET
if: steps.should-run.outputs.run == 'true'
uses: actions/setup-dotnet@v5
with:
dotnet-version: 10.0.x
- name: Cache NuGet
if: steps.should-run.outputs.run == 'true'
uses: actions/cache@v5
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }}
restore-keys: |
${{ runner.os }}-nuget-
# Clean up legacy manual files before generation
# Only delete specific service interface/implementation files that will be replaced
- name: Clean up legacy files
if: steps.should-run.outputs.run == 'true'
shell: pwsh
run: |
# Map tool to package directory and namespace prefix
$toolMap = @{
"choco" = @{ Package = "ModularPipelines.Chocolatey"; Prefix = "Choco" }
"winget" = @{ Package = "ModularPipelines.WinGet"; Prefix = "Winget" }
}
$toolInfo = $toolMap["${{ matrix.tool }}"]
if ($toolInfo) {
$package = $toolInfo.Package
$prefix = $toolInfo.Prefix
$pkgDir = "src/$package"
if (Test-Path $pkgDir) {
Write-Host "Cleaning up legacy files in $pkgDir for prefix $prefix..."
# Only delete specific service interface/implementation files (not all I*.cs files)
# These are the exact files the generator will create in Services/
$interfaceFile = Join-Path $pkgDir "I$prefix.cs"
$implFile = Join-Path $pkgDir "$prefix.cs"
if (Test-Path $interfaceFile) {
Remove-Item $interfaceFile -Force -ErrorAction SilentlyContinue
Write-Host "Removed $interfaceFile"
}
if (Test-Path $implFile) {
Remove-Item $implFile -Force -ErrorAction SilentlyContinue
Write-Host "Removed $implFile"
}
# Delete old .Generated.cs files in Services folder (will be replaced with non-.Generated names)
$servicesDir = Join-Path $pkgDir "Services"
if (Test-Path $servicesDir) {
Get-ChildItem -Path $servicesDir -Filter "*.Generated.cs" -File -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue
}
Write-Host "Cleanup complete for $package"
}
}
- name: Install Chocolatey
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'choco'
shell: pwsh
run: |
# Chocolatey is pre-installed on windows-latest
choco --version
- name: Install WinGet
if: steps.should-run.outputs.run == 'true' && matrix.tool == 'winget'
shell: pwsh
run: |
# WinGet is pre-installed on windows-latest (Windows Server 2022)
winget --version
- name: Build Generator
if: steps.should-run.outputs.run == 'true'
run: dotnet build -c Release
working-directory: tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator
- name: Run Generator for ${{ matrix.tool }}
if: steps.should-run.outputs.run == 'true'
shell: pwsh
run: |
dotnet run -c Release -- `
--tools "${{ matrix.tool }}" `
--output-dir "${{ github.workspace }}"
working-directory: tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator
- name: Check for changes
if: steps.should-run.outputs.run == 'true'
id: changes
shell: pwsh
run: |
git add -A
$diff = git diff --staged --quiet; $hasChanges = $LASTEXITCODE -ne 0
if ($hasChanges) {
"has_changes=true" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
Write-Host "Changed files:"
git diff --staged --name-only
} else {
"has_changes=false" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
}
- name: Build solution to verify changes
if: steps.should-run.outputs.run == 'true' && steps.changes.outputs.has_changes == 'true'
run: dotnet build ModularPipelines.sln -c Release
- name: Create Pull Request for ${{ matrix.tool }}
id: create-pr
if: steps.should-run.outputs.run == 'true' && steps.changes.outputs.has_changes == 'true' && (github.event.inputs.create-pr != 'false')
uses: peter-evans/create-pull-request@v8
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: "chore: Update ${{ matrix.tool }} CLI options"
title: "[Automated] Update ${{ matrix.tool }} CLI Options"
body: |
## Summary
This PR contains automatically generated updates to **${{ matrix.tool }}** CLI options classes.
The generator scraped the latest CLI help output from the installed tool.
## Changes
- Updated options classes to reflect latest CLI documentation
- Added new commands if any were detected
- Updated option types and descriptions
## Verification
- [x] Solution builds successfully
---
🤖 Generated with ModularPipelines.OptionsGenerator
branch: automated/update-cli-options-${{ matrix.tool }}
base: main
delete-branch: true
labels: |
automated
dependencies
- name: Enable auto-merge
if: steps.create-pr.outputs.pull-request-number
shell: pwsh
run: gh pr merge ${{ steps.create-pr.outputs.pull-request-number }} --auto --squash
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}