Skip to content

Fix mounting path from /safedata to /safe_data in documentation a… #79

Fix mounting path from /safedata to /safe_data in documentation a…

Fix mounting path from /safedata to /safe_data in documentation a… #79

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/^/ - /'