Skip to content

[fix] Modify Dockerfile to fix ci errors. #18

[fix] Modify Dockerfile to fix ci errors.

[fix] Modify Dockerfile to fix ci errors. #18

Workflow file for this run

name: Docker Development Environment CI
on:
push:
branches:
- main
- develop
pull_request:
branches:
- main
- develop
workflow_dispatch: # Allow manual trigger
env:
# CI environment variable to control script behavior
CI: true
jobs:
build-and-test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
# Ubuntu 20.04 - Minimal mode
- os_version: ubuntu2004
build_mode: minimal
display_name: "Ubuntu 20.04 (Minimal)"
# Ubuntu 20.04 - Full mode
- os_version: ubuntu2004
build_mode: full
display_name: "Ubuntu 20.04 (Full)"
# Ubuntu 22.04 - Minimal mode
- os_version: ubuntu2204
build_mode: minimal
display_name: "Ubuntu 22.04 (Minimal)"
# Ubuntu 22.04 - Full mode
- os_version: ubuntu2204
build_mode: full
display_name: "Ubuntu 22.04 (Full)"
# CentOS 7 - Minimal mode
- os_version: centos7
build_mode: minimal
display_name: "CentOS 7 (Minimal)"
# CentOS 7 - Full mode
- os_version: centos7
build_mode: full
display_name: "CentOS 7 (Full)"
name: Build & Test - ${{ matrix.display_name }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker environment
run: |
# Ensure Docker is running
sudo systemctl start docker
sudo systemctl enable docker
# Add current user to docker group (though we'll use sudo for CI)
sudo usermod -aG docker $USER
- name: Free up disk space
run: |
# Remove unnecessary packages to free up space
sudo apt-get remove -y '^dotnet-.*' || true
sudo apt-get remove -y '^llvm-.*' || true
sudo apt-get remove -y 'php.*' || true
sudo apt-get remove -y '^mono-.*' || true
sudo apt-get remove -y '^ghc-.*' || true
sudo apt-get autoremove -y
sudo apt-get clean
# Show available disk space
df -h
- name: Create scripts directory
run: |
mkdir -p scripts
# Create a dummy set_proxy.sh if it doesn't exist
if [ ! -f scripts/set_proxy.sh ]; then
echo '#!/bin/bash' > scripts/set_proxy.sh
echo 'echo "Proxy script placeholder"' >> scripts/set_proxy.sh
chmod +x scripts/set_proxy.sh
fi
- name: Make setup.sh executable
run: chmod +x ./setup.sh
- name: Show configuration
run: ./setup.sh -o ${{ matrix.os_version }} -m ${{ matrix.build_mode }} -c
- name: Build Docker image and run container using setup.sh
id: build_and_run
run: |
# Create logs directory
mkdir -p logs
# Use the setup script to build and run the container
./setup.sh -o ${{ matrix.os_version }} -m ${{ matrix.build_mode }} -b || {
echo "Error: setup.sh failed with exit code $?"
echo "SETUP SCRIPT ERROR" > logs/container_logs.txt
echo "Command './setup.sh -o ${{ matrix.os_version }} -m ${{ matrix.build_mode }} -b' failed with exit code $?" >> logs/container_logs.txt
docker ps -a >> logs/container_logs.txt
docker images >> logs/container_logs.txt
echo "Docker daemon logs:" >> logs/container_logs.txt
sudo journalctl -u docker.service -n 50 >> logs/container_logs.txt 2>&1 || true
echo "FAILED=true" >> $GITHUB_ENV
exit 1
}
# Capture container name for later steps
HOST_USER=$(whoami)
CONTAINER_USER="sheen"
CONTAINER_NAME="dev_${{ matrix.os_version }}_${{ matrix.build_mode }}_${CONTAINER_USER}"
if [ -z "$CONTAINER_NAME" ]; then
echo "Error: Container not created or not running"
echo "CONTAINER NOT FOUND" > logs/container_logs.txt
echo "Container was not created or is not running" >> logs/container_logs.txt
echo "Docker containers:" >> logs/container_logs.txt
docker ps -a >> logs/container_logs.txt
echo "Docker images:" >> logs/container_logs.txt
docker images >> logs/container_logs.txt
echo "FAILED=true" >> $GITHUB_ENV
exit 1
fi
echo "container_name=$CONTAINER_NAME" >> $GITHUB_OUTPUT
echo "Container name: $CONTAINER_NAME"
- name: Get container IP using setup.sh
id: container_ip
run: |
# Use setup.sh to query IP
./setup.sh -o ${{ matrix.os_version }} -m ${{ matrix.build_mode }} -i
# Also capture IP for later steps
CONTAINER_NAME="${{ steps.build_and_run.outputs.container_name }}"
CONTAINER_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$CONTAINER_NAME")
echo "container_ip=$CONTAINER_IP" >> $GITHUB_OUTPUT
echo "Container IP: $CONTAINER_IP"
- name: Verify container is running
if: steps.build_and_run.outputs.container_name != ''
run: |
CONTAINER_NAME="${{ steps.build_and_run.outputs.container_name }}"
echo "Verifying container: $CONTAINER_NAME"
# Check container status
docker ps --filter "name=$CONTAINER_NAME"
# Check container logs
echo "Container logs:"
docker logs "$CONTAINER_NAME" || true
- name: Test container basic functionality
if: steps.build_and_run.outputs.container_name != ''
run: |
CONTAINER_NAME="${{ steps.build_and_run.outputs.container_name }}"
echo "Testing container functionality..."
# Test if SSH service is running
docker exec "$CONTAINER_NAME" systemctl status ssh || docker exec "$CONTAINER_NAME" service ssh status || docker exec "$CONTAINER_NAME" ps aux | grep sshd
# Test SSH port is listening
docker exec "$CONTAINER_NAME" netstat -tlnp | grep :22 || docker exec "$CONTAINER_NAME" ss -tlnp | grep :22
- name: Test user environment
id: test_user_env
if: steps.build_and_run.outputs.container_name != ''
run: |
CONTAINER_NAME="${{ steps.build_and_run.outputs.container_name }}"
BUILD_MODE="${{ matrix.build_mode }}"
# Create log directory
mkdir -p logs
# Test user home directory structure
echo "Checking user home directory:"
docker exec "$CONTAINER_NAME" ls -la /home/sheen/ > logs/home_dir.log 2>&1
cat logs/home_dir.log
# Test workspace directory mount
echo "Testing workspace mount:"
docker exec "$CONTAINER_NAME" ls -la /home/sheen/workspace/ > logs/workspace_mount.log 2>&1 || echo "Workspace mount issue detected" >> logs/workspace_mount.log
cat logs/workspace_mount.log
# Create container info and logs early for debugging
echo "Container information:" > logs/container_info.txt
docker inspect "$CONTAINER_NAME" >> logs/container_info.txt 2>&1 || echo "Failed to inspect container" >> logs/container_info.txt
docker logs "$CONTAINER_NAME" > logs/container_logs.txt 2>&1 || echo "Failed to get container logs" >> logs/container_logs.txt
# Test shell based on build mode
if [ "$BUILD_MODE" = "full" ]; then
echo "Testing ZSH setup (full mode):"
{
docker exec "$CONTAINER_NAME" which zsh || echo "ZSH binary not found"
docker exec -u sheen "$CONTAINER_NAME" bash -c 'echo $SHELL' || echo "Failed to check default shell"
docker exec -u sheen "$CONTAINER_NAME" zsh -c 'echo "ZSH works"' || echo "ZSH execution failed"
docker exec -u sheen "$CONTAINER_NAME" test -f ~/.zshrc && echo "ZSH config exists" || echo "ZSH config not found"
} > logs/shell_test.log 2>&1
cat logs/shell_test.log
# Exit with error if ZSH test fails in full mode
if ! grep -q "ZSH works" logs/shell_test.log; then
echo "::error::ZSH functionality test failed in full mode. See detailed logs for more information."
echo "FAILED=true" >> $GITHUB_ENV
exit 1
fi
else
echo "Testing Bash setup (minimal mode):"
{
docker exec "$CONTAINER_NAME" which bash || echo "Bash binary not found"
docker exec -u sheen "$CONTAINER_NAME" bash -c 'echo "Bash works"' || echo "Bash execution failed"
docker exec "$CONTAINER_NAME" which zsh && echo "WARNING: ZSH found in minimal mode" || echo "ZSH correctly not installed"
} > logs/shell_test.log 2>&1
cat logs/shell_test.log
# Exit with error if Bash test fails in minimal mode
if ! grep -q "Bash works" logs/shell_test.log; then
echo "::error::Bash functionality test failed in minimal mode. See detailed logs for more information."
echo "FAILED=true" >> $GITHUB_ENV
exit 1
fi
fi
- name: Test installed development tools
id: test_dev_tools
if: steps.build_and_run.outputs.container_name != '' && success()
run: |
CONTAINER_NAME="${{ steps.build_and_run.outputs.container_name }}"
BUILD_MODE="${{ matrix.build_mode }}"
# Test basic tools (available in all modes)
echo "Testing development tools:"
{
docker exec "$CONTAINER_NAME" which gcc || echo "gcc not found"
docker exec "$CONTAINER_NAME" which python3 || echo "python3 not found"
docker exec "$CONTAINER_NAME" which git || echo "git not found"
docker exec "$CONTAINER_NAME" which cmake || echo "cmake not found"
} > logs/dev_tools.log 2>&1
cat logs/dev_tools.log
# Test for LLVM/Clang (only in full mode)
if [ "$BUILD_MODE" = "full" ]; then
echo "Testing LLVM/Clang installation (full mode):"
{
docker exec "$CONTAINER_NAME" which clang || echo "clang not found in full mode"
docker exec "$CONTAINER_NAME" clang --version || echo "clang version check failed"
} > logs/llvm.log 2>&1
cat logs/llvm.log
else
echo "Testing LLVM/Clang absence (minimal mode):"
{
docker exec "$CONTAINER_NAME" which clang && echo "WARNING: clang found in minimal mode" || echo "clang correctly not installed"
} > logs/llvm.log 2>&1
cat logs/llvm.log
fi
# Test for conda (only in full mode)
if [ "$BUILD_MODE" = "full" ]; then
echo "Testing conda installation (full mode):"
docker exec -u sheen "$CONTAINER_NAME" bash -c '[ -d "$HOME/miniconda3" ] && echo "Miniconda directory exists" || echo "Miniconda not installed"' > logs/conda.log 2>&1
else
echo "Skipping conda test (minimal mode)"
echo "Conda not expected in minimal mode" > logs/conda.log
fi
cat logs/conda.log
- name: Test helper functions and fallback configuration
id: test_helpers
if: steps.build_and_run.outputs.container_name != '' && success()
run: |
CONTAINER_NAME="${{ steps.build_and_run.outputs.container_name }}"
BUILD_MODE="${{ matrix.build_mode }}"
# Only test helper functions in full mode with ZSH
if [ "$BUILD_MODE" = "full" ]; then
# Check if zsh helper functions are defined
echo "Testing helper functions:"
{
docker exec -u sheen "$CONTAINER_NAME" zsh -c 'type install_omz' || echo "Helper install_omz not defined, but continuing"
docker exec -u sheen "$CONTAINER_NAME" zsh -c 'type install_zsh_plugins' || echo "Helper install_zsh_plugins not defined, but continuing"
} > logs/helper_functions.log 2>&1
cat logs/helper_functions.log
# Check if Oh My Zsh is installed
echo "Checking Oh My Zsh installation:"
docker exec -u sheen "$CONTAINER_NAME" zsh -c '[ -d "$HOME/.oh-my-zsh" ] && echo "Oh My Zsh installed" || echo "Oh My Zsh not installed (using fallback)"' > logs/omz.log 2>&1
cat logs/omz.log
else
echo "Skipping helper function tests (minimal mode - no ZSH)"
echo "Helper functions not expected in minimal mode" > logs/helper_functions.log
echo "Oh My Zsh not expected in minimal mode" > logs/omz.log
fi
- name: Run security checks
id: security_checks
if: steps.build_and_run.outputs.container_name != '' && success()
run: |
CONTAINER_NAME="${{ steps.build_and_run.outputs.container_name }}"
# Check for common security issues
echo "Running security checks..."
{
# Check SSH directory permissions
echo "SSH directory permissions:"
docker exec "$CONTAINER_NAME" stat -c "%a %n" /home/sheen/.ssh/
docker exec "$CONTAINER_NAME" stat -c "%a %n" /home/sheen/.ssh/authorized_keys || echo "authorized_keys not found or not accessible"
# Check sudo access
echo "Sudo access check:"
docker exec -u sheen "$CONTAINER_NAME" sudo -l || echo "Sudo verification failed but continuing"
} > logs/security.log 2>&1
cat logs/security.log
- name: Collect all logs
if: always()
run: |
# Ensure logs directory exists
mkdir -p logs
# Combine all logs and add timestamps
echo "==== CI SUMMARY ====" > logs/combined.log
echo "Date: $(date)" >> logs/combined.log
echo "OS Version: ${{ matrix.os_version }}" >> logs/combined.log
echo "Build Mode: ${{ matrix.build_mode }}" >> logs/combined.log
if [[ "${{ job.status }}" == "success" ]]; then
echo "CI Status: SUCCESS" >> logs/combined.log
echo "All tests passed successfully." >> logs/combined.log
else
echo "CI Status: FAILED" >> logs/combined.log
echo "Detailed failure information:" >> logs/combined.log
# Add important container info
CONTAINER_NAME="${{ steps.build_and_run.outputs.container_name }}"
if [[ -n "$CONTAINER_NAME" ]]; then
echo "Container: $CONTAINER_NAME" >> logs/combined.log
docker ps -a --filter "name=$CONTAINER_NAME" --format "{{.ID}} {{.Image}} {{.Status}}" >> logs/combined.log
docker inspect "$CONTAINER_NAME" --format "{{.State.Status}}" >> logs/combined.log
docker logs "$CONTAINER_NAME" >> logs/combined.log 2>&1 || echo "Failed to get container logs" >> logs/combined.log
else
echo "Container not created or name not captured" >> logs/combined.log
fi
# Get step outcome information
echo "Step outcomes:" >> logs/combined.log
echo "- Build container: ${{ steps.build_and_run.outcome }}" >> logs/combined.log
echo "- User environment: ${{ steps.test_user_env.outcome || 'Not run' }}" >> logs/combined.log
echo "- Development tools: ${{ steps.test_dev_tools.outcome || 'Not run' }}" >> logs/combined.log
echo "- Helper functions: ${{ steps.test_helpers.outcome || 'Not run' }}" >> logs/combined.log
echo "- Security checks: ${{ steps.security_checks.outcome || 'Not run' }}" >> logs/combined.log
fi
# List of any log files
echo -e "\nLog files available:" >> logs/combined.log
ls -la logs/ >> logs/combined.log 2>&1 || echo "No log files found" >> logs/combined.log
# Print summary to console
cat logs/combined.log
- name: Export container information
if: always() && steps.build_and_run.outputs.container_name != ''
run: |
CONTAINER_NAME="${{ steps.build_and_run.outputs.container_name }}"
# Export container info for debugging (append if files already exist)
if [ ! -f logs/container_info.txt ]; then
echo "Container information:" > logs/container_info.txt
docker inspect "$CONTAINER_NAME" >> logs/container_info.txt 2>&1 || echo "Failed to inspect container" >> logs/container_info.txt
fi
if [ ! -f logs/container_logs.txt ]; then
# Save container logs
docker logs "$CONTAINER_NAME" > logs/container_logs.txt 2>&1 || echo "Failed to get container logs" >> logs/container_logs.txt
fi
# Add additional diagnostics
echo "Docker info:" >> logs/container_info.txt
docker info >> logs/container_info.txt 2>&1 || true
- name: Upload artifacts on failure
if: failure() || env.FAILED == 'true'
uses: actions/upload-artifact@v4
with:
name: debug-info-${{ matrix.os_version }}-${{ matrix.build_mode }}
path: |
logs/
retention-days: 7
- name: Upload success artifacts
if: success() && env.FAILED != 'true'
uses: actions/upload-artifact@v4
with:
name: ci-summary-${{ matrix.os_version }}-${{ matrix.build_mode }}
path: |
logs/combined.log
retention-days: 3
- name: Clean up container using setup.sh
if: always() && steps.build_and_run.outputs.container_name != ''
run: |
echo "Cleaning up container with setup.sh"
./setup.sh -o ${{ matrix.os_version }} -m ${{ matrix.build_mode }} -s
# Verify cleanup
CONTAINER_NAME="${{ steps.build_and_run.outputs.container_name }}"
if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "Warning: Container wasn't removed by setup.sh, removing manually"
docker rm -f "$CONTAINER_NAME" || true
fi
- name: Show final disk usage
if: always()
run: |
echo "Final disk usage:"
df -h
echo "Docker images:"
docker images
echo "Docker containers:"
docker ps -a