Fix mounting path from /safedata to /safe_data in documentation a…
#79
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: Build and Publish Dev Container | |
| on: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| inputs: | |
| vscode_commit: | |
| description: 'VS Code commit hash to use (defaults to Dockerfile declaration if not provided)' | |
| required: false | |
| type: string | |
| env: | |
| REGISTRY: ghcr.io | |
| IMAGE_NAME: ${{ github.repository }} | |
| jobs: | |
| build-and-publish: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: write # For publishing container images | |
| pull-requests: write # For PR comments from security scan | |
| actions: write # For uploading artifacts from security scan | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Resolve VSCODE_COMMIT (input override > Dockerfile default) | |
| id: vscode-commit | |
| run: | | |
| # If user provided an input, trust it. Otherwise parse Dockerfile ARG default. | |
| if [ -n "${{ github.event.inputs.vscode_commit }}" ]; then | |
| VSCODE_COMMIT="${{ github.event.inputs.vscode_commit }}" | |
| SOURCE="workflow_input" | |
| else | |
| # Extract default from ARG line: ARG VSCODE_COMMIT=<hash> | |
| VSCODE_COMMIT=$(grep -E '^ARG VSCODE_COMMIT=' Dockerfile | head -n1 | cut -d= -f2-) | |
| if [ -z "$VSCODE_COMMIT" ]; then | |
| echo "❌ Could not find default VSCODE_COMMIT in Dockerfile" >&2 | |
| exit 1 | |
| fi | |
| SOURCE="dockerfile_default" | |
| fi | |
| # Basic validation (40 hex chars) | |
| if ! echo "$VSCODE_COMMIT" | grep -Eq '^[0-9a-f]{40}$'; then | |
| echo "❌ VSCODE_COMMIT '$VSCODE_COMMIT' is not a 40-char hex commit hash" >&2 | |
| exit 1 | |
| fi | |
| VSCODE_SHORT=${VSCODE_COMMIT:0:7} | |
| echo "Resolved VSCODE_COMMIT=$VSCODE_COMMIT (source=$SOURCE)" | |
| echo "vscode_commit=$VSCODE_COMMIT" >> $GITHUB_OUTPUT | |
| echo "vscode_short=$VSCODE_SHORT" >> $GITHUB_OUTPUT | |
| echo "source=$SOURCE" >> $GITHUB_OUTPUT | |
| echo "Short: $VSCODE_SHORT" | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| tags: | | |
| type=ref,event=branch | |
| type=ref,event=pr | |
| type=ref,event=tag | |
| # Tags for default branch (main) only | |
| type=sha,prefix={{branch}}-,enable={{is_default_branch}} | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| type=raw,value=vscode-${{ steps.vscode-commit.outputs.vscode_short }},enable={{is_default_branch}} | |
| type=raw,value=vscode-${{ steps.vscode-commit.outputs.vscode_short }}-{{sha}},enable={{is_default_branch}} | |
| # Tags for PRs only | |
| type=ref,prefix=pr-,suffix=-${{ steps.vscode-commit.outputs.vscode_short }},event=pr | |
| type=ref,prefix=pr-,suffix=-${{ steps.vscode-commit.outputs.vscode_short }}-{{sha}},event=pr | |
| - name: Extract tag names only | |
| id: tags | |
| run: | | |
| # Extract just the tag portions (everything after the last colon) | |
| TAGS=$(echo '${{ steps.meta.outputs.tags }}' | sed 's/.*://' | tr '\n' ',' | sed 's/,$//') | |
| echo "tags=$TAGS" >> $GITHUB_OUTPUT | |
| echo "Extracted tags: $TAGS" | |
| - name: Build and publish dev container | |
| uses: devcontainers/ci@v0.3 | |
| env: | |
| VSCODE_COMMIT: ${{ steps.vscode-commit.outputs.vscode_commit }} | |
| with: | |
| imageName: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| imageTag: ${{ steps.tags.outputs.tags }} | |
| cacheFrom: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| push: always | |
| # Test the container with a simple validation | |
| runCmd: | | |
| echo "=== Testing dev container ===" | |
| echo "Python: $(python3 --version)" | |
| echo "Git: $(git --version)" | |
| echo "Pip: $(pip3 --version)" | |
| # Test Python import | |
| python3 -c "import sys; print(f'Python executable: {sys.executable}')" | |
| # Test if common development tools are available | |
| if command -v zsh &> /dev/null; then | |
| echo "Zsh: $(zsh --version)" | |
| fi | |
| if command -v quarto &> /dev/null; then | |
| echo "Quarto: $(quarto --version)" | |
| else | |
| echo "Quarto: Not found (this may be expected)" | |
| fi | |
| echo "=== Dev container validation completed! ===" | |
| # Free up disk space before security scan to prevent "no space left on device" errors | |
| - name: Free Disk Space | |
| run: | | |
| echo "=== Disk space before cleanup ===" | |
| df -h | |
| echo "=== Removing unnecessary files ===" | |
| sudo rm -rf /usr/share/dotnet | |
| sudo rm -rf /usr/local/lib/android | |
| sudo rm -rf /opt/ghc | |
| sudo rm -rf /opt/hostedtoolcache/CodeQL | |
| sudo apt-get clean | |
| echo "=== Disk space after cleanup ===" | |
| df -h | |
| # Using the custom Trivy Security Scan action from this repository | |
| - name: Security Scan | |
| id: security-scan | |
| uses: smartdatafoundry/trivy-security-scan@v1.0.0 | |
| with: | |
| image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| registry: ${{ env.REGISTRY }} | |
| severity: 'CRITICAL,HIGH' | |
| detailed-severity: 'CRITICAL,HIGH,MEDIUM,LOW' | |
| ignore-unfixed: 'true' | |
| exit-code: '0' | |
| artifact-name: 'security-scan-results' | |
| artifact-retention-days: '30' | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| post-pr-comment: 'true' | |
| # Optional: Handle scan results programmatically | |
| - name: Process scan results | |
| run: | | |
| echo "Security scan status: ${{ steps.security-scan.outputs.scan-status }}" | |
| echo "Vulnerabilities found: ${{ steps.security-scan.outputs.vulnerability-count }}" | |
| echo "Artifact ID: ${{ steps.security-scan.outputs.artifact-id }}" | |
| # You can add custom logic here based on the scan results | |
| if [ "${{ steps.security-scan.outputs.scan-status }}" = "vulnerabilities_found" ]; then | |
| echo "⚠️ Security vulnerabilities detected!" | |
| echo "Consider reviewing the security report before deploying." | |
| # Optionally, you could fail the build for critical vulnerabilities: | |
| # if [ "${{ steps.security-scan.outputs.vulnerability-count }}" -gt "10" ]; then | |
| # echo "❌ Too many vulnerabilities found (> 10), failing build" | |
| # exit 1 | |
| # fi | |
| else | |
| echo "✅ No critical or high severity vulnerabilities found!" | |
| fi | |
| - name: Container info | |
| if: success() | |
| run: | | |
| echo "✅ Dev container built and published successfully!" | |
| echo "📦 Registry: ${{ env.REGISTRY }}" | |
| echo "🏷️ Image: ${{ env.IMAGE_NAME }}" | |
| echo "🆔 Tags: ${{ steps.meta.outputs.tags }}" | |
| echo "📝 Labels: ${{ steps.meta.outputs.labels }}" | |
| echo "🔧 VSCode Commit: ${{ steps.vscode-commit.outputs.vscode_commit }}" | |
| echo "📋 Short Commit: ${{ steps.vscode-commit.outputs.vscode_short }}" | |
| echo "🗂️ Source: ${{ steps.vscode-commit.outputs.source }}" | |
| echo "" | |
| echo "To use this dev container:" | |
| echo "1. Reference it in your devcontainer.json:" | |
| echo ' "image": "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:<tag>"' | |
| echo "2. Or use it directly with Docker:" | |
| echo " docker run --rm -it ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:<tag>" | |
| echo "" | |
| echo "Available tags:" | |
| echo "${{ steps.meta.outputs.tags }}" | tr ',' '\n' | sed 's/^/ - /' |