Skip to content

fix(security): bump gh 2.90.0, yq 4.53.2 to address CVEs #213

fix(security): bump gh 2.90.0, yq 4.53.2 to address CVEs

fix(security): bump gh 2.90.0, yq 4.53.2 to address CVEs #213

Workflow file for this run

name: "v2: CI"
# v2 Bash/Docker CI Pipeline
# Triggers on changes to v2 directory and related configurations
on:
push:
branches: [main, develop]
paths:
- 'v2/**'
- '.github/workflows/ci-v2.yml'
- '.github/actions/shared/**'
- 'package.json'
pull_request:
branches: [main, develop]
paths:
- 'v2/**'
- '.github/workflows/ci-v2.yml'
- '.github/actions/shared/**'
- 'package.json'
workflow_dispatch:
inputs:
providers:
description: |
Providers to test (comma-separated or 'all').
Options: docker, fly, devpod-aws, devpod-gcp, devpod-azure, devpod-do, devpod-k8s
required: false
default: "docker,fly,devpod-k8s"
type: string
test-level:
description: Test level to run
required: false
default: "profile"
type: choice
options:
- quick
- extension
- profile
- all
extension-profile:
description: Extension profile to test (affects resource requirements)
required: false
default: "minimal"
type: choice
options:
- minimal
- mobile
- fullstack
- ai-dev
- systems
- devops
- anthropic-dev
- enterprise
- visionflow-core
- visionflow-data-scientist
- visionflow-creative
- visionflow-full
extension:
description: Extension to test (when test-level is 'extension')
required: false
default: "nodejs"
type: string
skip-cleanup:
description: Skip resource cleanup for debugging
required: false
default: false
type: boolean
concurrency:
group: ci-v2-${{ github.ref }}
cancel-in-progress: true
env:
DOCKER_BUILDKIT: 1
jobs:
# NOTE: Validation is handled by dedicated workflows:
# - validate-shell.yml (shellcheck)
# - validate-markdown.yml (markdownlint)
# - validate-yaml.yml (YAML/schema validation)
# ============================================
# Build Job
# ============================================
build:
name: Build v2 Docker Image
runs-on: ubuntu-latest
permissions:
contents: read
packages: write # NEW: for GHCR push
outputs:
image-tag: ${{ steps.build.outputs.tag }}
image-digest: ${{ steps.build.outputs.digest }}
image-ref: ${{ steps.meta.outputs.tags }}
steps:
- uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
# NEW: Login to GHCR
- name: Login to GHCR
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# NEW: Generate metadata with CI tags
# NOTE: Use full SHA (${{ github.sha }}) not {{sha}} template (which gives short SHA)
# to ensure consistency between build tags and artifact save step
- name: Generate metadata
id: meta
uses: docker/metadata-action@v6
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=raw,value=v2-ci-${{ github.sha }}
labels: |
org.opencontainers.image.title=Sindri v2
org.opencontainers.image.description=Multi-cloud development environment orchestrator
sindri.version=v2
sindri.ci.run=${{ github.run_id }}
sindri.ci.branch=${{ github.ref_name }}
# MODIFIED: Build with fresh layers + push to GHCR
- name: Build and push to GHCR
id: build
uses: docker/build-push-action@v7
with:
context: .
file: v2/Dockerfile
push: true # NEW: Push to registry
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64 # Required for single-platform image with attestations
no-cache: true # NEW: Fresh builds
pull: true # NEW: Latest base images
secrets: |
github_token=${{ secrets.GITHUB_TOKEN }}
provenance: mode=max
sbom: true
# NOTE: Image is pushed to GHCR and pulled directly by test jobs
# This avoids attestation/provenance issues with artifact-based distribution
- name: Export image metadata
run: |
echo "tag=ghcr.io/${{ github.repository }}:v2-ci-${{ github.sha }}" >> $GITHUB_OUTPUT
echo "✅ Image built and pushed"
echo " Image: ghcr.io/${{ github.repository }}:v2-ci-${{ github.sha }}"
echo " Note: Test jobs will pull directly from GHCR"
# ============================================
# Test Matrix Generation
# ============================================
generate-matrix:
name: Generate Test Matrix
runs-on: ubuntu-latest
outputs:
providers: ${{ steps.matrix.outputs.providers }}
steps:
- uses: actions/checkout@v6
- name: Generate matrices
id: matrix
run: |
# Determine which providers to test based on trigger type
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
INPUT_PROVIDERS="${{ github.event.inputs.providers }}"
if [[ "$INPUT_PROVIDERS" == "all" ]]; then
PROVIDERS='["docker", "fly", "devpod-aws", "devpod-gcp", "devpod-azure", "devpod-do", "devpod-k8s"]'
else
PROVIDERS=$(echo "$INPUT_PROVIDERS" | jq -Rc 'split(",") | map(ltrimstr(" ") | rtrimstr(" "))')
fi
else
# Push and PR events all test the same provider set
PROVIDERS='["docker", "fly", "devpod-k8s"]'
fi
# Skip fly provider for Dependabot PRs (no access to FLY_API_TOKEN secret)
if [[ "${{ github.actor }}" == "dependabot[bot]" ]]; then
PROVIDERS=$(echo "$PROVIDERS" | jq -c 'map(select(. != "fly"))')
echo "::notice title=Dependabot Detected::Skipping fly provider (no secret access)"
fi
echo "providers=$PROVIDERS" >> $GITHUB_OUTPUT
echo "::notice title=Test Providers::$PROVIDERS"
# ============================================
# Security Scanning
# ============================================
security-scan:
name: Security Scan
needs: build
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
security-events: write
steps:
- uses: actions/checkout@v6
- name: Login to GHCR
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Scan with Trivy
uses: aquasecurity/trivy-action@0.35.0
with:
image-ref: ghcr.io/${{ github.repository }}:v2-ci-${{ github.sha }}
format: sarif
output: trivy-results.sarif
severity: CRITICAL,HIGH,MEDIUM
ignore-unfixed: true
- name: Upload to GitHub Security
uses: github/codeql-action/upload-sarif@v4
if: always()
with:
sarif_file: trivy-results.sarif
- name: Scan summary
if: always()
run: |
echo "## Security Scan Results" >> $GITHUB_STEP_SUMMARY
echo "Image: \`ghcr.io/${{ github.repository }}:v2-ci-${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ -f trivy-results.sarif ]; then
ISSUES=$(jq '.runs[0].results | length' trivy-results.sarif)
echo "- **Issues Found**: $ISSUES" >> $GITHUB_STEP_SUMMARY
fi
# ============================================
# Unified Provider Testing
# ============================================
test-docker:
name: Test v2 on Docker
needs: [build, generate-matrix]
if: contains(fromJson(needs.generate-matrix.outputs.providers), 'docker')
uses: ./.github/workflows/v2-test-provider.yml
with:
provider: docker
test-level: ${{ github.event.inputs.test-level || 'profile' }}
extension-profile: ${{ github.event.inputs.extension-profile || 'minimal' }}
extension: ${{ github.event.inputs.extension || 'nodejs' }}
skip-cleanup: ${{ github.event.inputs.skip-cleanup == 'true' }}
image: ghcr.io/${{ github.repository }}:v2-ci-${{ github.sha }}
use-registry: true
secrets: inherit
test-fly:
name: Test v2 on Fly.io
needs: [build, generate-matrix]
if: contains(fromJson(needs.generate-matrix.outputs.providers), 'fly')
uses: ./.github/workflows/v2-test-provider.yml
with:
provider: fly
test-level: ${{ github.event.inputs.test-level || 'profile' }}
extension-profile: ${{ github.event.inputs.extension-profile || 'minimal' }}
extension: ${{ github.event.inputs.extension || 'nodejs' }}
skip-cleanup: ${{ github.event.inputs.skip-cleanup == 'true' }}
image: ghcr.io/${{ github.repository }}:v2-ci-${{ github.sha }}
use-registry: true
secrets: inherit
test-devpod-k8s:
name: Test v2 on DevPod K8s
needs: [build, generate-matrix]
if: contains(fromJson(needs.generate-matrix.outputs.providers), 'devpod-k8s')
uses: ./.github/workflows/v2-test-provider.yml
with:
provider: devpod-k8s
test-level: ${{ github.event.inputs.test-level || 'profile' }}
extension-profile: ${{ github.event.inputs.extension-profile || 'minimal' }}
extension: ${{ github.event.inputs.extension || 'nodejs' }}
skip-cleanup: ${{ github.event.inputs.skip-cleanup == 'true' }}
image: ghcr.io/${{ github.repository }}:v2-ci-${{ github.sha }}
use-registry: true
secrets: inherit
# ============================================
# Mark Promotion Candidate
# ============================================
mark-passed:
name: Mark as Promotion Candidate
needs: [build, security-scan, test-docker, test-fly, test-devpod-k8s]
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Login to GHCR
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Tag as promotion candidate
run: |
echo "Pulling CI image..."
docker pull ghcr.io/${{ github.repository }}:v2-ci-${{ github.sha }}
echo "Tagging as v2-ci-passed..."
docker tag ghcr.io/${{ github.repository }}:v2-ci-${{ github.sha }} \
ghcr.io/${{ github.repository }}:v2-ci-passed-${{ github.sha }}
echo "Pushing promotion candidate tag..."
docker push ghcr.io/${{ github.repository }}:v2-ci-passed-${{ github.sha }}
echo "✅ Image marked as promotion candidate"
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Promotion Candidate" >> $GITHUB_STEP_SUMMARY
echo "- **Image**: \`ghcr.io/${{ github.repository }}:v2-ci-passed-${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY
echo "- **Status**: Ready for release promotion" >> $GITHUB_STEP_SUMMARY
echo "- **Tests**: All provider tests passed" >> $GITHUB_STEP_SUMMARY
echo "- **Security**: Vulnerability scan completed" >> $GITHUB_STEP_SUMMARY
# ============================================
# CI Status Checks
# ============================================
ci-required:
name: CI v2 Required Checks
runs-on: ubuntu-latest
needs:
- build
- security-scan
if: ${{ always() }}
steps:
- name: Check required jobs
run: |
# Check if any required job failed
# NOTE: Validation is handled by dedicated workflows:
# - validate-shell.yml, validate-markdown.yml, validate-yaml.yml
BUILD="${{ needs.build.result }}"
SECURITY="${{ needs.security-scan.result }}"
if [[ "$BUILD" != "success" ]]; then
echo "❌ Required CI v2 checks failed"
echo "Results:"
echo " build: $BUILD"
echo " security-scan: $SECURITY"
exit 1
fi
if [[ "$SECURITY" != "success" ]]; then
echo "⚠️ Security scan failed but not blocking"
echo " security-scan: $SECURITY"
fi
echo "✅ Required CI v2 checks passed"
ci-status:
name: CI v2 Status
runs-on: ubuntu-latest
needs:
- ci-required
- test-docker
- test-fly
- test-devpod-k8s
if: ${{ always() }}
steps:
- name: Check overall status
run: |
REQUIRED="${{ needs.ci-required.result }}"
TEST_DOCKER="${{ needs.test-docker.result }}"
TEST_FLY="${{ needs.test-fly.result }}"
TEST_DEVPOD_K8S="${{ needs.test-devpod-k8s.result }}"
# Required checks must pass
if [[ "$REQUIRED" != "success" ]]; then
echo "❌ CI v2 failed - required checks did not pass"
exit 1
fi
# Provider tests should pass if they ran
if [[ "$TEST_DOCKER" != "skipped" ]] && [[ "$TEST_DOCKER" != "success" ]]; then
echo "❌ CI v2 failed - docker provider tests failed"
echo " test-docker: $TEST_DOCKER"
exit 1
fi
if [[ "$TEST_FLY" != "skipped" ]] && [[ "$TEST_FLY" != "success" ]]; then
echo "❌ CI v2 failed - fly provider tests failed"
echo " test-fly: $TEST_FLY"
exit 1
fi
if [[ "$TEST_DEVPOD_K8S" != "skipped" ]] && [[ "$TEST_DEVPOD_K8S" != "success" ]]; then
echo "❌ CI v2 failed - devpod-k8s provider tests failed"
echo " test-devpod-k8s: $TEST_DEVPOD_K8S"
exit 1
fi
echo "✅ CI v2 passed"
echo "Results:"
echo " ci-required: $REQUIRED"
echo " test-docker: $TEST_DOCKER"
echo " test-fly: $TEST_FLY"
echo " test-devpod-k8s: $TEST_DEVPOD_K8S"
- name: Generate summary
if: always()
run: |
echo "# CI v2 Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Unified Provider Testing (v2)" >> $GITHUB_STEP_SUMMARY
echo "Each selected provider receives **complete test coverage**:" >> $GITHUB_STEP_SUMMARY
echo "- CLI Tests (sindri, extension-manager commands)" >> $GITHUB_STEP_SUMMARY
echo "- Extension Tests (validation, installation)" >> $GITHUB_STEP_SUMMARY
echo "- Integration Tests (end-to-end workflows)" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Job Results" >> $GITHUB_STEP_SUMMARY
echo "| Job | Status |" >> $GITHUB_STEP_SUMMARY
echo "|-----|--------|" >> $GITHUB_STEP_SUMMARY
echo "| Required Checks | ${{ needs.ci-required.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| Test Docker | ${{ needs.test-docker.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| Test Fly.io | ${{ needs.test-fly.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| Test DevPod K8s | ${{ needs.test-devpod-k8s.result }} |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Metadata" >> $GITHUB_STEP_SUMMARY
echo "- **Version**: v2 (Bash/Docker)" >> $GITHUB_STEP_SUMMARY
echo "- **Triggered by**: ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY
echo "- **Branch**: ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY
echo "- **Commit**: ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
echo "- **Run**: ${{ github.run_id }}" >> $GITHUB_STEP_SUMMARY