feat: improve command logging with compact format and buffered module… #70
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: Generate CLI Options | ||
| 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 }} | ||