Skip to content

Merge pull request #17 from unplugged12/dependabot/github_actions/anc… #48

Merge pull request #17 from unplugged12/dependabot/github_actions/anc…

Merge pull request #17 from unplugged12/dependabot/github_actions/anc… #48

Workflow file for this run

name: CI Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
jobs:
lint-powershell:
name: Lint PowerShell Scripts
runs-on: windows-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Ensure PSScriptAnalyzer
shell: pwsh
run: |
if (-not (Get-Module -ListAvailable -Name PSScriptAnalyzer)) {
Install-Module -Name PSScriptAnalyzer -Force -Scope CurrentUser
}
- name: Check PowerShell formatting
shell: pwsh
run: |
./tools/lint.ps1 -Mode FormatCheck
- name: Run PSScriptAnalyzer
shell: pwsh
run: |
./tools/lint.ps1 -Mode Analyze -FailOnNewWarnings
lint-bash:
name: Lint Bash Scripts
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install shellcheck
run: |
sudo apt-get update
sudo apt-get install -y shellcheck
- name: Run shellcheck
run: |
find . -name "*.sh" -type f | while read -r script; do
echo "Analyzing: $script"
shellcheck "$script" || exit 1
done
echo "✓ All Bash scripts passed linting"
validate-scripts:
name: Validate Scripts (Windows)
runs-on: windows-latest
needs: [lint-powershell]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Check Docker availability
shell: pwsh
run: |
$dockerCmd = Get-Command docker -ErrorAction SilentlyContinue
if (-not $dockerCmd) {
Write-Warning "Docker executable not found. Skipping Docker version check."
}
else {
docker --version
}
- name: Run pre-deployment validation
shell: pwsh
run: |
# Skip checks that require network access in CI
Write-Host "Running syntax validation..."
# Validate PowerShell scripts execute without errors
$scripts = Get-ChildItem -Path scripts -Filter *.ps1 -Recurse
foreach ($script in $scripts) {
Write-Host "Syntax check: $($script.Name)"
$null = [System.Management.Automation.PSParser]::Tokenize((Get-Content $script.FullName -Raw), [ref]$null)
}
Write-Host "✓ All scripts are syntactically valid"
security-sast:
name: Security - SAST Scanning
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run Trivy vulnerability scanner
uses: aquasecurity/[email protected]
with:
scan-type: 'fs'
scan-ref: '.'
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
- name: Upload Trivy results to GitHub Security
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: 'trivy-results.sarif'
- name: Run Semgrep SAST
uses: returntocorp/semgrep-action@v1
with:
config: >-
p/security-audit
p/secrets
validate-docker-compose:
name: Validate Docker Compose Files
runs-on: ubuntu-latest
strategy:
matrix:
stack: [common, desktop, laptop]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Validate compose file - ${{ matrix.stack }}
run: |
cd stacks/${{ matrix.stack }}
# Create dummy env file for validation
echo "MCP_ENV_FILE=/tmp/mcp.env" > .env.test
echo "HUB_USERNAME=testuser" >> .env.test
echo "HUB_PAT_TOKEN=testtoken" >> .env.test
echo "CONTEXT7_TOKEN=testtoken" >> .env.test
echo "ENVIRONMENT=ci" >> .env.test
# Create dummy secret file referenced by MCP_ENV_FILE so docker compose validation succeeds
printf "# dummy MCP env file for CI validation\n" > /tmp/mcp.env
# Validate compose file syntax
docker compose --env-file .env.test config > /dev/null
if [ $? -eq 0 ]; then
echo "✓ ${{ matrix.stack }}/docker-compose.yml is valid"
else
echo "✗ ${{ matrix.stack }}/docker-compose.yml validation failed"
exit 1
fi
security-sbom:
name: Generate SBOM
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Generate SBOM with Syft
uses: anchore/[email protected]
with:
path: ./
format: 'cyclonedx-json'
output-file: 'sbom.json'
upload-artifact: false
- name: Upload SBOM as artifact
uses: actions/upload-artifact@v4
with:
name: sbom
path: sbom.json
retention-days: 90
- name: Scan SBOM with Grype
uses: anchore/scan-action@v3
with:
sbom: 'sbom.json'
fail-build: false
severity-cutoff: high
docker-image-checks:
name: Docker Image Security Scan
runs-on: ubuntu-latest
strategy:
matrix:
image:
- mcp/context7:latest
- mcp/dockerhub:latest
- mcp/mcp-playwright:latest
- mcp/sequentialthinking:latest
steps:
- name: Run Trivy vulnerability scanner on image
uses: aquasecurity/[email protected]
with:
image-ref: ${{ matrix.image }}
format: 'table'
severity: 'CRITICAL,HIGH'
ignore-unfixed: true
exit-code: 1
test-scripts-linux:
name: Test Scripts (Linux)
runs-on: ubuntu-latest
needs: [lint-bash]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Docker
run: |
docker --version
- name: Test script execution
run: |
# Make scripts executable
find scripts -name "*.sh" -type f -exec chmod +x {} \;
# Test that scripts don't have syntax errors
find scripts -name "*.sh" -type f | while read -r script; do
echo "Testing: $script"
bash -n "$script" || exit 1
done
echo "✓ All Bash scripts are executable and valid"
test-scripts-windows:
name: Test Scripts (Windows)
runs-on: windows-latest
needs: [lint-powershell, validate-scripts]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Pester
shell: pwsh
run: |
if (-not (Get-Module -ListAvailable -Name Pester -ErrorAction Ignore | Where-Object { $_.Version.Major -ge 5 })) {
Install-Module -Name Pester -Force -SkipPublisherCheck -Scope CurrentUser
}
- name: Run PowerShell test suite
shell: pwsh
run: |
./scripts/run-tests.ps1 -CI
- name: Publish Pester results
if: always()
uses: actions/upload-artifact@v4
with:
name: pester-results
path: TestResults/test-results.xml
retention-days: 14
summary:
name: CI Summary
runs-on: ubuntu-latest
needs:
- lint-powershell
- lint-bash
- validate-scripts
- security-sast
- validate-docker-compose
- security-sbom
- docker-image-checks
- test-scripts-linux
- test-scripts-windows
if: always()
steps:
- name: Check job results
run: |
echo "## CI Pipeline Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Job Results:" >> $GITHUB_STEP_SUMMARY
echo "- Lint PowerShell: ${{ needs.lint-powershell.result }}" >> $GITHUB_STEP_SUMMARY
echo "- Lint Bash: ${{ needs.lint-bash.result }}" >> $GITHUB_STEP_SUMMARY
echo "- Validate Scripts: ${{ needs.validate-scripts.result }}" >> $GITHUB_STEP_SUMMARY
echo "- Security SAST: ${{ needs.security-sast.result }}" >> $GITHUB_STEP_SUMMARY
echo "- Validate Docker Compose: ${{ needs.validate-docker-compose.result }}" >> $GITHUB_STEP_SUMMARY
echo "- Generate SBOM: ${{ needs.security-sbom.result }}" >> $GITHUB_STEP_SUMMARY
echo "- Docker Image Security: ${{ needs.docker-image-checks.result }}" >> $GITHUB_STEP_SUMMARY
echo "- Test Scripts (Linux): ${{ needs.test-scripts-linux.result }}" >> $GITHUB_STEP_SUMMARY
echo "- Test Scripts (Windows): ${{ needs.test-scripts-windows.result }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ "${{ needs.lint-powershell.result }}" != "success" ] || \
[ "${{ needs.lint-bash.result }}" != "success" ] || \
[ "${{ needs.validate-scripts.result }}" != "success" ] || \
[ "${{ needs.validate-docker-compose.result }}" != "success" ] || \
[ "${{ needs.test-scripts-linux.result }}" != "success" ] || \
[ "${{ needs.test-scripts-windows.result }}" != "success" ]; then
echo "❌ CI Pipeline Failed" >> $GITHUB_STEP_SUMMARY
exit 1
else
echo "✅ CI Pipeline Passed" >> $GITHUB_STEP_SUMMARY
fi