[fix] Modify Dockerfile to fix ci errors. #18
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: 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 |