Skip to content

Development Containers (CI) #10

Development Containers (CI)

Development Containers (CI) #10

---
# Note: Keep keys and envs in alphabetical order.
name: Development Containers (CI)
# yamllint disable-line rule:truthy
on:
pull_request:
paths:
- .devcontainer/**
- .github/workflows/devcontainer-ci.yml
push:
branches:
- master
paths:
- .devcontainer/**
- .github/workflows/devcontainer-ci.yml
schedule:
- cron: 0 0 * * 1 # Run every Monday at 00:00 UTC
workflow_call:
# IMPORTANT: When calling this reusable workflow from another repository,
# you MUST grant 'packages: write' permission in the calling workflow.
# Example:
# jobs:
# devcontainer:
# uses: FX31337/.github/.github/workflows/devcontainer-ci.yml@master
# permissions:
# contents: read
# packages: write # Required for pushing to GitHub Container Registry
inputs:
required_commands:
description: Space-separated list of required command-line tools
required: false
type: string
default: ''
required_python_packages:
description: Space-separated list of required Python packages
required: false
type: string
default: ''
env:
# Keep the commands and packages in lexicographical order.
REQUIRED_COMMANDS: >-
${{ inputs.required_commands != '' && inputs.required_commands || 'actionlint
ansible
docker
gh
make
node
npm
pip
pre-commit
python3
rg' }}
REQUIRED_PYTHON_PACKAGES: >-
${{ inputs.required_python_packages != '' && inputs.required_python_packages || 'ansible
ansible-lint
docker
molecule
pre-commit
uv' }}
permissions:
contents: read
packages: write
jobs:
devcontainer-build:
name: Build & Test
permissions:
contents: read
packages: write # Enables push to GHCR
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set image name
id: image
run: |
# Transform repository name to valid Docker tag format
# 1. Convert to lowercase (Docker tags must be lowercase)
# 2. Remove leading dots from path components (Docker components must start with alphanumeric)
REPO_NAME="${{ github.repository }}"
REPO_LOWER="${REPO_NAME,,}"
# Remove /. pattern to handle repos like "org/.github" -> "org/github"
SAFE_REPO_NAME="${REPO_LOWER//\/\./\/}"
echo "name=ghcr.io/${SAFE_REPO_NAME}/devcontainer" >> "$GITHUB_OUTPUT"
- name: Check cache image existence
id: cache_check
continue-on-error: true
run: |
IMAGE_NAME="${{ steps.image.outputs.name }}"
echo "Checking if cache image exists: ${IMAGE_NAME}:latest"
if docker pull "${IMAGE_NAME}:latest" 2>/dev/null; then
echo "✓ Cache image found: ${IMAGE_NAME}:latest"
echo "exists=true" >> "$GITHUB_OUTPUT"
else
echo "⚠ Cache image not found: ${IMAGE_NAME}:latest"
echo "⚠ Build will proceed without cache (first build or image expired)"
echo "exists=false" >> "$GITHUB_OUTPUT"
fi
- name: Build and test dev container
uses: devcontainers/ci@v0.3
with:
imageName: ${{ steps.image.outputs.name }}
cacheFrom: ${{ steps.image.outputs.name }}
push: filter
refFilterForPush: refs/heads/master
runCmd: |-
echo "Testing devcontainer build..."
# Check all required commands are installed
echo "Checking required command-line tools..."
for cmd in $REQUIRED_COMMANDS; do
if ! command -v "$cmd" &> /dev/null; then
echo "✗ $cmd is not installed"
exit 1
fi
echo "✓ $cmd is installed"
done
# Check all required Python packages are installed
echo "Checking required Python packages..."
for pkg in $REQUIRED_PYTHON_PACKAGES; do
if ! python3 -m pip show "$pkg" &> /dev/null; then
echo "✗ Required Python package '$pkg' is missing"
exit 1
fi
echo "✓ $pkg is installed"
done
echo "✓ All required Python packages are installed"
# Verify pre-commit can run (hooks may not be installed in CI container)
if pre-commit --version &> /dev/null; then
echo "✓ pre-commit is functional"
else
echo "✗ pre-commit is not functional"
exit 1
fi
echo "✓ All devcontainer tests passed!"