Build and Publish Dev Container #49
Workflow file for this run
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: | |
| pull_request: | |
| branches: | |
| - main | |
| paths: | |
| - '.devcontainer/**' | |
| - '.github/workflows/build-devcontainer.yml' | |
| workflow_dispatch: | |
| inputs: | |
| vscode_commit: | |
| description: 'VS Code commit hash to use' | |
| required: true | |
| type: string | |
| env: | |
| # Set a default VS Code commit hash for tagging purposes | |
| # This can be overridden via workflow_dispatch input if needed | |
| # For PRs, the default value will be used | |
| VSCODE_COMMIT: ${{ github.event.inputs.vscode_commit || 'OTHER' }} | |
| 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: | |
| # Write a step to test recieving the VSCODE_COMMIT input and fail | |
| - name: Debug VSCODE_COMMIT input | |
| run: | | |
| echo "Received VSCODE_COMMIT input: '${{ github.event.inputs.vscode_commit }}'" | |
| if [ -z "${{ env.VSCODE_COMMIT }}" ]; then | |
| echo "❌ VSCODE_COMMIT is not set. Failing the build." | |
| else | |
| echo "✅ VSCODE_COMMIT is set to '${{ env.VSCODE_COMMIT }}'" | |
| fi | |
| exit 1 | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Set VSCODE_COMMIT for tagging | |
| id: vscode-commit | |
| run: | | |
| # For manual dispatch, use the input; for PRs use default value for tagging | |
| VSCODE_COMMIT="${{ env.VSCODE_COMMIT }}" | |
| VSCODE_SHORT=${VSCODE_COMMIT:0:7} | |
| echo "vscode_commit=$VSCODE_COMMIT" >> $GITHUB_OUTPUT | |
| echo "vscode_short=$VSCODE_SHORT" >> $GITHUB_OUTPUT | |
| - 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 | |
| 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 }} | |
| type=raw,value=vscode-${{ steps.vscode-commit.outputs.vscode_short }}-{{sha}} | |
| - 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! ===" | |
| # 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 "" | |
| 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/^/ - /' |