mirror of https://github.com/bohanyang/debi
Merge 2723453053 into 5cdd2d6f5b
commit
25daf447b6
2 changed files with 633 additions and 0 deletions
@ -0,0 +1,218 @@ |
|||||||
|
# GitHub Actions Workflow for Testing debi.sh |
||||||
|
|
||||||
|
## Overview |
||||||
|
|
||||||
|
This workflow tests the Debian Network Reinstall Script (`debi.sh`) using KVM virtualization in GitHub Actions. It validates that the script correctly prepares a system for Debian installation, performs the actual installation, and verifies the newly installed system. |
||||||
|
|
||||||
|
## Test Matrix |
||||||
|
|
||||||
|
The workflow uses a semantic matrix strategy to test ~15 different configurations across: |
||||||
|
|
||||||
|
- **Debian Versions**: 10 (Buster), 11 (Bullseye), 12 (Bookworm) |
||||||
|
- **Mirrors**: Default, USTC (China), Cloudflare |
||||||
|
- **Network Interface Naming**: Standard (`ethx`) or predictable names |
||||||
|
- **User Account**: `root` or `debian` |
||||||
|
- **Network Console**: Always enabled for remote installation monitoring |
||||||
|
|
||||||
|
**Key combinations tested:** |
||||||
|
- Debian 10 with default mirror (baseline) |
||||||
|
- Debian 11 with all mirrors and both naming schemes |
||||||
|
- Debian 12 with all mirrors and various user configurations |
||||||
|
|
||||||
|
**Base Image**: All tests use Debian 11 (Bullseye) cloud image as the starting point, regardless of target version. |
||||||
|
|
||||||
|
## How It Works |
||||||
|
|
||||||
|
### 1. Environment Setup |
||||||
|
- Enables KVM support on GitHub Actions runner |
||||||
|
- Caches APT packages for faster subsequent runs |
||||||
|
- Installs QEMU and related tools (qemu-kvm, cloud-utils, sshpass, etc.) |
||||||
|
|
||||||
|
### 2. Base Image Caching |
||||||
|
- Downloads Debian 11 cloud image (only once, then cached) |
||||||
|
- Reuses cached image across all matrix jobs |
||||||
|
- Significantly speeds up workflow execution |
||||||
|
|
||||||
|
### 3. VM Preparation |
||||||
|
- Creates a copy-on-write disk image from the cached base image |
||||||
|
- Generates cloud-init configuration for initial VM setup |
||||||
|
- Configures root SSH access with password `rootpass123` |
||||||
|
|
||||||
|
### 4. VM Execution |
||||||
|
- Starts QEMU VM with KVM acceleration |
||||||
|
- Waits for SSH to become available |
||||||
|
- Uploads `debi.sh` script to the VM |
||||||
|
|
||||||
|
### 5. Script Testing |
||||||
|
- **Builds arguments dynamically** from matrix parameters: |
||||||
|
- `--version` from `matrix.version` |
||||||
|
- `--ustc` or `--cloudflare` from `matrix.mirror` |
||||||
|
- `--ethx` from `matrix.ethx` |
||||||
|
- `--network-console` (always enabled) |
||||||
|
- `--user` and `--password` from `matrix.user` |
||||||
|
- Executes `debi.sh` with built arguments |
||||||
|
- Captures output for debugging |
||||||
|
|
||||||
|
### 6. Installation Validation |
||||||
|
The workflow validates that the script: |
||||||
|
- Successfully downloads Debian installer components to `/boot/debian-*/` |
||||||
|
- Creates the required `linux` and `initrd.gz` files |
||||||
|
- Updates GRUB configuration with Debian Installer entry |
||||||
|
- Sets GRUB default to boot into the installer |
||||||
|
|
||||||
|
### 7. Full Installation Test |
||||||
|
After validation, the workflow: |
||||||
|
- Reboots the VM to start the Debian installer |
||||||
|
- Waits for the installation to complete (up to 30 minutes) |
||||||
|
- Polls for SSH availability with the **new password** (`newpass123`) |
||||||
|
- Verifies the newly installed system |
||||||
|
|
||||||
|
### 7. Success Criteria |
||||||
|
|
||||||
|
A test passes if: |
||||||
|
- ✓ Script executes without critical errors |
||||||
|
- ✓ Installer files exist in `/boot/debian-*/` |
||||||
|
- ✓ GRUB configuration contains "Debian Installer" entry |
||||||
|
- ✓ VM successfully reboots into installer |
||||||
|
- ✓ Installation completes automatically |
||||||
|
- ✓ New system boots and is accessible via SSH with new credentials |
||||||
|
|
||||||
|
## Running the Tests |
||||||
|
|
||||||
|
### Automatic Execution |
||||||
|
Tests run automatically on: |
||||||
|
- Push to `master` or `main` branch |
||||||
|
- Pull requests targeting `master` or `main` |
||||||
|
|
||||||
|
### Manual Execution |
||||||
|
You can manually trigger the workflow: |
||||||
|
1. Go to Actions tab in GitHub |
||||||
|
2. Select "Test Debian Installation Script" |
||||||
|
3. Click "Run workflow" |
||||||
|
|
||||||
|
## Test Artifacts |
||||||
|
|
||||||
|
Each test run uploads: |
||||||
|
- `debi-output.log` - Complete output from script execution |
||||||
|
- `serial.log` - VM serial console log |
||||||
|
|
||||||
|
Access artifacts from the workflow run summary page. |
||||||
|
|
||||||
|
## Interpreting Results |
||||||
|
|
||||||
|
### ✅ Success |
||||||
|
- All validation checks pass |
||||||
|
- New system is accessible with new credentials |
||||||
|
- Green checkmark in GitHub Actions UI |
||||||
|
|
||||||
|
### ❌ Failure |
||||||
|
Common failure scenarios and debugging: |
||||||
|
|
||||||
|
1. **SSH connection timeout (old credentials)** |
||||||
|
- Check serial console log |
||||||
|
- Verify cloud-init configuration |
||||||
|
|
||||||
|
2. **Installer files not downloaded** |
||||||
|
- Review debi-output.log |
||||||
|
- Check network connectivity |
||||||
|
- Verify mirror availability |
||||||
|
|
||||||
|
3. **GRUB update failed** |
||||||
|
- Check for GRUB installation issues |
||||||
|
- Verify disk partitioning |
||||||
|
|
||||||
|
4. **Installation timeout** |
||||||
|
- Installation may take longer than expected |
||||||
|
- Check serial console for installer progress |
||||||
|
- Verify network connectivity to mirrors |
||||||
|
|
||||||
|
5. **Cannot connect with new credentials** |
||||||
|
- Installation may have failed |
||||||
|
- Check serial console for installation errors |
||||||
|
- Verify preseed configuration |
||||||
|
|
||||||
|
## Password Strategy |
||||||
|
|
||||||
|
The workflow uses two different passwords to verify installation success: |
||||||
|
|
||||||
|
| Phase | User | Password | Purpose | |
||||||
|
|-------|------|----------|---------| |
||||||
|
| Initial VM (cloud-init) | root | `rootpass123` | Access the base system to run debi.sh | |
||||||
|
| New System (installed) | root/debian | `newpass123` | Verify the new system was installed | |
||||||
|
|
||||||
|
If SSH connects with `newpass123`, it proves the new Debian system was installed successfully. |
||||||
|
|
||||||
|
## Limitations |
||||||
|
|
||||||
|
This workflow tests the complete installation process: |
||||||
|
- ✓ Script argument parsing |
||||||
|
- ✓ Installer file downloads |
||||||
|
- ✓ GRUB configuration updates |
||||||
|
- ✓ Reboot into installer |
||||||
|
- ✓ Unattended installation |
||||||
|
- ✓ New system verification |
||||||
|
|
||||||
|
Note: Full installation takes 10-30 minutes per test case. |
||||||
|
|
||||||
|
## Performance Optimization |
||||||
|
|
||||||
|
The workflow includes several optimizations: |
||||||
|
|
||||||
|
1. **APT Package Caching**: Dependencies are cached across workflow runs |
||||||
|
2. **Base Image Caching**: Debian 11 cloud image is downloaded once and reused |
||||||
|
3. **Single Base Image**: All tests use Debian 11 as starting point (smaller cache footprint) |
||||||
|
4. **Matrix Exclusions**: Intelligent filtering reduces redundant test combinations |
||||||
|
|
||||||
|
## Adding New Test Cases |
||||||
|
|
||||||
|
The workflow uses a semantic matrix. To modify test coverage: |
||||||
|
|
||||||
|
**Add a new Debian version:** |
||||||
|
```yaml |
||||||
|
matrix: |
||||||
|
version: [10, 11, 12, 13] # Add 13 |
||||||
|
``` |
||||||
|
|
||||||
|
**Test with a new mirror:** |
||||||
|
```yaml |
||||||
|
matrix: |
||||||
|
mirror: ['default', 'ustc', 'cloudflare', 'tuna'] # Add tuna |
||||||
|
``` |
||||||
|
|
||||||
|
**Modify exclusions:** |
||||||
|
```yaml |
||||||
|
exclude: |
||||||
|
# Add exclusions to prevent unwanted combinations |
||||||
|
- version: 13 |
||||||
|
mirror: 'ustc' # Skip USTC for Debian 13 |
||||||
|
``` |
||||||
|
|
||||||
|
The workflow automatically builds command-line arguments from matrix parameters. |
||||||
|
|
||||||
|
## Troubleshooting |
||||||
|
|
||||||
|
### KVM not available |
||||||
|
If KVM is not available, the workflow will fail. GitHub Actions runners support KVM, but some self-hosted runners may not. |
||||||
|
|
||||||
|
### Network timeouts |
||||||
|
If downloads fail, consider: |
||||||
|
- Adding retry logic |
||||||
|
- Using alternative mirrors |
||||||
|
- Checking GitHub Actions network restrictions |
||||||
|
|
||||||
|
### VM boot failures |
||||||
|
Check the serial console log artifact for kernel messages and boot errors. |
||||||
|
|
||||||
|
### Installation hangs |
||||||
|
If the installation takes too long: |
||||||
|
- Check the serial console for progress |
||||||
|
- Verify mirror connectivity |
||||||
|
- Consider using a faster mirror (USTC, Cloudflare) |
||||||
|
|
||||||
|
### Cache issues |
||||||
|
To clear caches and force fresh downloads: |
||||||
|
1. Go to Actions tab → Caches |
||||||
|
2. Delete relevant cache entries |
||||||
|
3. Re-run the workflow |
||||||
|
|
||||||
|
Cache keys are based on workflow file hash, so modifying the workflow automatically invalidates caches. |
||||||
@ -0,0 +1,415 @@ |
|||||||
|
name: Test Debian Installation Script |
||||||
|
|
||||||
|
on: |
||||||
|
push: |
||||||
|
branches: [ master, main ] |
||||||
|
pull_request: |
||||||
|
branches: [ master, main ] |
||||||
|
workflow_dispatch: |
||||||
|
|
||||||
|
jobs: |
||||||
|
test-debi: |
||||||
|
name: "Debian ${{ matrix.version }} | ${{ matrix.mirror }} | ethx:${{ matrix.ethx }} | user:${{ matrix.user }} | nc:${{ matrix.network_console }}" |
||||||
|
runs-on: ubuntu-22.04 |
||||||
|
timeout-minutes: 45 |
||||||
|
|
||||||
|
permissions: |
||||||
|
contents: read |
||||||
|
|
||||||
|
strategy: |
||||||
|
fail-fast: false |
||||||
|
matrix: |
||||||
|
# Target Debian version to install |
||||||
|
version: [10, 11, 12] |
||||||
|
# Mirror configuration |
||||||
|
mirror: ['default', 'ustc', 'cloudflare'] |
||||||
|
# Network interface naming |
||||||
|
ethx: [true, false] |
||||||
|
# User to create |
||||||
|
user: ['root', 'debian'] |
||||||
|
# Enable network console for remote installation |
||||||
|
network_console: [true] |
||||||
|
|
||||||
|
# Exclude combinations to keep matrix manageable (~12 tests) |
||||||
|
exclude: |
||||||
|
# Debian 10 - only test with default mirror and root user |
||||||
|
- version: 10 |
||||||
|
mirror: 'ustc' |
||||||
|
- version: 10 |
||||||
|
mirror: 'cloudflare' |
||||||
|
- version: 10 |
||||||
|
user: 'debian' |
||||||
|
- version: 10 |
||||||
|
ethx: false |
||||||
|
|
||||||
|
# For Debian 11 & 12, test key combinations |
||||||
|
# Skip debian user with ustc (redundant) |
||||||
|
- version: 11 |
||||||
|
mirror: 'ustc' |
||||||
|
user: 'debian' |
||||||
|
- version: 12 |
||||||
|
mirror: 'ustc' |
||||||
|
user: 'debian' |
||||||
|
|
||||||
|
# Skip cloudflare without ethx (less common) |
||||||
|
- mirror: 'cloudflare' |
||||||
|
ethx: false |
||||||
|
|
||||||
|
# Skip default mirror without ethx for Debian 12 |
||||||
|
- version: 12 |
||||||
|
mirror: 'default' |
||||||
|
ethx: false |
||||||
|
|
||||||
|
steps: |
||||||
|
- name: Checkout repository |
||||||
|
uses: actions/checkout@v4 |
||||||
|
|
||||||
|
- name: Enable KVM |
||||||
|
run: | |
||||||
|
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules |
||||||
|
sudo udevadm control --reload-rules |
||||||
|
sudo udevadm trigger --name-match=kvm |
||||||
|
|
||||||
|
- name: Cache APT packages |
||||||
|
uses: actions/cache@v4 |
||||||
|
id: cache-apt |
||||||
|
with: |
||||||
|
path: ~/apt-cache |
||||||
|
key: ${{ runner.os }}-apt-${{ hashFiles('.github/workflows/test.yml') }} |
||||||
|
restore-keys: | |
||||||
|
${{ runner.os }}-apt- |
||||||
|
|
||||||
|
- name: Restore APT cache |
||||||
|
if: steps.cache-apt.outputs.cache-hit == 'true' |
||||||
|
run: | |
||||||
|
if [ -d ~/apt-cache ] && [ "$(ls -A ~/apt-cache 2>/dev/null)" ]; then |
||||||
|
sudo cp ~/apt-cache/*.deb /var/cache/apt/archives/ 2>/dev/null || true |
||||||
|
fi |
||||||
|
|
||||||
|
- name: Install dependencies |
||||||
|
run: | |
||||||
|
sudo apt-get update |
||||||
|
sudo apt-get install -y qemu-kvm qemu-utils cloud-image-utils genisoimage expect sshpass |
||||||
|
|
||||||
|
- name: Save APT cache |
||||||
|
if: steps.cache-apt.outputs.cache-hit != 'true' |
||||||
|
run: | |
||||||
|
mkdir -p ~/apt-cache |
||||||
|
sudo cp /var/cache/apt/archives/*.deb ~/apt-cache/ 2>/dev/null || true |
||||||
|
sudo chown -R $USER:$USER ~/apt-cache |
||||||
|
|
||||||
|
- name: Check KVM availability |
||||||
|
run: | |
||||||
|
ls -la /dev/kvm |
||||||
|
kvm-ok || true |
||||||
|
|
||||||
|
- name: Cache Debian cloud image |
||||||
|
id: cache-debian-image |
||||||
|
uses: actions/cache@v4 |
||||||
|
with: |
||||||
|
path: /tmp/debian-11-base.qcow2 |
||||||
|
key: debian-11-cloud-image-${{ hashFiles('.github/workflows/test.yml') }} |
||||||
|
restore-keys: | |
||||||
|
debian-11-cloud-image- |
||||||
|
|
||||||
|
- name: Download Debian 11 cloud image |
||||||
|
if: steps.cache-debian-image.outputs.cache-hit != 'true' |
||||||
|
run: | |
||||||
|
wget -O /tmp/debian-11-base.qcow2 "https://cloud.debian.org/images/cloud/bullseye/latest/debian-11-generic-amd64.qcow2" |
||||||
|
|
||||||
|
- name: Create working disk image |
||||||
|
run: | |
||||||
|
qemu-img create -f qcow2 -F qcow2 -b /tmp/debian-11-base.qcow2 /tmp/test-disk.qcow2 20G |
||||||
|
qemu-img resize /tmp/test-disk.qcow2 20G |
||||||
|
|
||||||
|
- name: Create cloud-init configuration |
||||||
|
run: | |
||||||
|
mkdir -p /tmp/cloud-init |
||||||
|
|
||||||
|
# meta-data |
||||||
|
cat > /tmp/cloud-init/meta-data << 'EOF' |
||||||
|
instance-id: test-debi-vm |
||||||
|
local-hostname: test-debi |
||||||
|
EOF |
||||||
|
|
||||||
|
# user-data with root access |
||||||
|
cat > /tmp/cloud-init/user-data << 'EOF' |
||||||
|
#cloud-config |
||||||
|
users: |
||||||
|
- name: root |
||||||
|
lock_passwd: false |
||||||
|
plain_text_passwd: 'rootpass123' |
||||||
|
|
||||||
|
ssh_pwauth: true |
||||||
|
disable_root: false |
||||||
|
|
||||||
|
packages: |
||||||
|
- wget |
||||||
|
- curl |
||||||
|
|
||||||
|
runcmd: |
||||||
|
- sed -i 's/^#PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config |
||||||
|
- systemctl restart sshd |
||||||
|
EOF |
||||||
|
|
||||||
|
# Create ISO for cloud-init |
||||||
|
genisoimage -output /tmp/cloud-init.iso \ |
||||||
|
-volid cidata -rational-rock -joliet \ |
||||||
|
/tmp/cloud-init/user-data /tmp/cloud-init/meta-data |
||||||
|
|
||||||
|
- name: Start VM and wait for boot |
||||||
|
run: | |
||||||
|
# Start QEMU in background (daemonize mode doesn't support -nographic) |
||||||
|
sudo qemu-system-x86_64 \ |
||||||
|
-machine type=pc,accel=kvm \ |
||||||
|
-cpu host \ |
||||||
|
-m 2048 \ |
||||||
|
-display none \ |
||||||
|
-drive file=/tmp/test-disk.qcow2,format=qcow2,if=virtio \ |
||||||
|
-cdrom /tmp/cloud-init.iso \ |
||||||
|
-net nic,model=virtio \ |
||||||
|
-net user,hostfwd=tcp::2222-:22 \ |
||||||
|
-serial file:/tmp/serial.log \ |
||||||
|
-monitor unix:/tmp/qemu-monitor.sock,server,nowait \ |
||||||
|
-daemonize |
||||||
|
|
||||||
|
# Fix permissions on serial.log so it can be uploaded as artifact |
||||||
|
sudo chmod 644 /tmp/serial.log |
||||||
|
|
||||||
|
echo "Waiting for VM to boot and SSH to become available..." |
||||||
|
for i in {1..60}; do |
||||||
|
if sshpass -p 'rootpass123' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p 2222 root@localhost 'echo SSH ready' 2>/dev/null; then |
||||||
|
echo "SSH is ready!" |
||||||
|
break |
||||||
|
fi |
||||||
|
echo "Attempt $i/60: Waiting for SSH..." |
||||||
|
sleep 5 |
||||||
|
done |
||||||
|
|
||||||
|
# Verify SSH is working |
||||||
|
sshpass -p 'rootpass123' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p 2222 root@localhost 'uname -a' |
||||||
|
|
||||||
|
- name: Upload debi.sh to VM |
||||||
|
run: | |
||||||
|
sshpass -p 'rootpass123' scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -P 2222 \ |
||||||
|
./debi.sh root@localhost:/root/debi.sh |
||||||
|
|
||||||
|
- name: Make script executable |
||||||
|
run: | |
||||||
|
sshpass -p 'rootpass123' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p 2222 root@localhost \ |
||||||
|
'chmod +x /root/debi.sh' |
||||||
|
|
||||||
|
- name: Build debi.sh arguments from matrix parameters |
||||||
|
id: build-args |
||||||
|
run: | |
||||||
|
# Start with version |
||||||
|
ARGS="--version ${{ matrix.version }}" |
||||||
|
|
||||||
|
# Add mirror flag |
||||||
|
if [ "${{ matrix.mirror }}" = "ustc" ]; then |
||||||
|
ARGS="$ARGS --ustc" |
||||||
|
elif [ "${{ matrix.mirror }}" = "cloudflare" ]; then |
||||||
|
ARGS="$ARGS --cloudflare" |
||||||
|
fi |
||||||
|
# default mirror doesn't need a flag |
||||||
|
|
||||||
|
# Add ethx flag |
||||||
|
if [ "${{ matrix.ethx }}" = "true" ]; then |
||||||
|
ARGS="$ARGS --ethx" |
||||||
|
fi |
||||||
|
|
||||||
|
# Add network-console flag |
||||||
|
if [ "${{ matrix.network_console }}" = "true" ]; then |
||||||
|
ARGS="$ARGS --network-console" |
||||||
|
fi |
||||||
|
|
||||||
|
# Add user and password |
||||||
|
ARGS="$ARGS --user ${{ matrix.user }} --password newpass123" |
||||||
|
|
||||||
|
echo "args=$ARGS" >> $GITHUB_OUTPUT |
||||||
|
echo "Generated arguments: $ARGS" |
||||||
|
|
||||||
|
- name: Run debi.sh with test arguments |
||||||
|
run: | |
||||||
|
echo "Running debi.sh with arguments: ${{ steps.build-args.outputs.args }}" |
||||||
|
|
||||||
|
# Run the script with a pseudo-TTY to handle stty commands |
||||||
|
# Use 'script' command to provide a PTY for non-interactive SSH |
||||||
|
sshpass -p 'rootpass123' ssh -t -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p 2222 root@localhost \ |
||||||
|
"script -q -c 'cd /root && ./debi.sh ${{ steps.build-args.outputs.args }}' /tmp/debi-output.log; echo \"Script exit code: \$?\" >> /tmp/debi-output.log" || echo "Script execution finished with non-zero exit code, will validate via file checks" |
||||||
|
|
||||||
|
- name: Download and check debi.sh output |
||||||
|
run: | |
||||||
|
sshpass -p 'rootpass123' scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -P 2222 \ |
||||||
|
root@localhost:/tmp/debi-output.log /tmp/debi-output.log || echo "Could not download output log" |
||||||
|
|
||||||
|
if [ -f /tmp/debi-output.log ]; then |
||||||
|
echo "=== debi.sh output ===" |
||||||
|
cat /tmp/debi-output.log |
||||||
|
echo "======================" |
||||||
|
fi |
||||||
|
|
||||||
|
- name: Verify installation preparation |
||||||
|
run: | |
||||||
|
echo "Checking if Debian installer files were downloaded..." |
||||||
|
|
||||||
|
# Check if installer directory was created |
||||||
|
sshpass -p 'rootpass123' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p 2222 root@localhost \ |
||||||
|
'ls -la /boot/debian-* || echo "No installer directory found"' |
||||||
|
|
||||||
|
# Check for installer components |
||||||
|
sshpass -p 'rootpass123' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p 2222 root@localhost \ |
||||||
|
'ls -lh /boot/debian-*/linux /boot/debian-*/initrd.gz 2>/dev/null || echo "Installer files not found"' |
||||||
|
|
||||||
|
# Check GRUB configuration |
||||||
|
sshpass -p 'rootpass123' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p 2222 root@localhost \ |
||||||
|
'cat /etc/default/grub.d/zz-debi.cfg 2>/dev/null || echo "GRUB config not found"' |
||||||
|
|
||||||
|
# Check if GRUB was updated with installer entry |
||||||
|
sshpass -p 'rootpass123' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p 2222 root@localhost \ |
||||||
|
'grep -A 5 "Debian Installer" /boot/grub/grub.cfg || echo "Debian Installer entry not found in GRUB"' |
||||||
|
|
||||||
|
- name: Validate installation files exist |
||||||
|
run: | |
||||||
|
# Verify key files exist |
||||||
|
sshpass -p 'rootpass123' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p 2222 root@localhost \ |
||||||
|
'test -f /boot/debian-*/linux && test -f /boot/debian-*/initrd.gz && echo "Installation files verified!" || exit 1' |
||||||
|
|
||||||
|
# Verify GRUB config was updated |
||||||
|
sshpass -p 'rootpass123' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p 2222 root@localhost \ |
||||||
|
'grep -q "Debian Installer" /boot/grub/grub.cfg && echo "GRUB config verified!" || exit 1' |
||||||
|
|
||||||
|
echo "✓ Script execution completed successfully" |
||||||
|
echo "✓ Installer files downloaded" |
||||||
|
echo "✓ GRUB configuration updated" |
||||||
|
echo "✓ System ready for reboot into Debian installer" |
||||||
|
|
||||||
|
- name: Reboot into Debian installer |
||||||
|
run: | |
||||||
|
echo "Rebooting VM to start Debian installation..." |
||||||
|
|
||||||
|
# Trigger reboot - the system should boot into Debian installer |
||||||
|
sshpass -p 'rootpass123' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p 2222 root@localhost \ |
||||||
|
'reboot' 2>/dev/null || true |
||||||
|
|
||||||
|
echo "Reboot command sent. VM will now boot into Debian installer." |
||||||
|
echo "The installation process will take several minutes..." |
||||||
|
|
||||||
|
- name: Wait for Debian installation to complete |
||||||
|
run: | |
||||||
|
echo "Waiting for Debian installation to complete..." |
||||||
|
echo "This typically takes 10-20 minutes depending on network speed and mirror." |
||||||
|
echo "The installer will automatically reboot after completion." |
||||||
|
|
||||||
|
# Wait for the old system to go down |
||||||
|
sleep 30 |
||||||
|
|
||||||
|
# The installation process: |
||||||
|
# 1. VM boots into Debian installer (netboot) |
||||||
|
# 2. Installer runs unattended using preseed configuration |
||||||
|
# 3. System installs packages from mirror |
||||||
|
# 4. System reboots into newly installed Debian |
||||||
|
|
||||||
|
# We'll poll for SSH availability with the NEW password |
||||||
|
# This indicates the new system has been installed and booted |
||||||
|
|
||||||
|
MAX_WAIT=1800 # 30 minutes maximum wait |
||||||
|
POLL_INTERVAL=30 |
||||||
|
ELAPSED=0 |
||||||
|
|
||||||
|
echo "Polling for new system availability (max wait: ${MAX_WAIT}s)..." |
||||||
|
|
||||||
|
while [ $ELAPSED -lt $MAX_WAIT ]; do |
||||||
|
echo "Attempt at ${ELAPSED}s: Trying to connect with new credentials..." |
||||||
|
|
||||||
|
# Try to connect with the NEW password (set by debi.sh installation) |
||||||
|
if sshpass -p 'newpass123' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=10 -p 2222 ${{ matrix.user }}@localhost 'echo "NEW SYSTEM CONNECTED!"' 2>/dev/null; then |
||||||
|
echo "✓ Successfully connected to newly installed system!" |
||||||
|
echo "✓ Installation completed successfully!" |
||||||
|
exit 0 |
||||||
|
fi |
||||||
|
|
||||||
|
# Also check if old system is still responding (installation not started yet) |
||||||
|
if sshpass -p 'rootpass123' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=5 -p 2222 root@localhost 'echo "old system"' 2>/dev/null; then |
||||||
|
echo " Old system still responding - installation may not have started" |
||||||
|
fi |
||||||
|
|
||||||
|
sleep $POLL_INTERVAL |
||||||
|
ELAPSED=$((ELAPSED + POLL_INTERVAL)) |
||||||
|
done |
||||||
|
|
||||||
|
echo "✗ Timeout: Could not connect to new system after ${MAX_WAIT}s" |
||||||
|
exit 1 |
||||||
|
|
||||||
|
- name: Verify new system installation |
||||||
|
run: | |
||||||
|
echo "Verifying the newly installed Debian system..." |
||||||
|
|
||||||
|
# Connect with new credentials and verify system |
||||||
|
sshpass -p 'newpass123' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p 2222 ${{ matrix.user }}@localhost << 'VERIFY_EOF' |
||||||
|
echo "=== System Information ===" |
||||||
|
uname -a |
||||||
|
|
||||||
|
echo "" |
||||||
|
echo "=== OS Release ===" |
||||||
|
cat /etc/os-release |
||||||
|
|
||||||
|
echo "" |
||||||
|
echo "=== Disk Usage ===" |
||||||
|
df -h |
||||||
|
|
||||||
|
echo "" |
||||||
|
echo "=== Memory Info ===" |
||||||
|
free -h |
||||||
|
|
||||||
|
echo "" |
||||||
|
echo "=== Network Configuration ===" |
||||||
|
ip addr show |
||||||
|
|
||||||
|
echo "" |
||||||
|
echo "=== Hostname ===" |
||||||
|
hostname |
||||||
|
|
||||||
|
echo "" |
||||||
|
echo "✓ New Debian system is running successfully!" |
||||||
|
VERIFY_EOF |
||||||
|
|
||||||
|
- name: Collect debug information on failure |
||||||
|
if: failure() |
||||||
|
run: | |
||||||
|
echo "=== Serial console log ===" |
||||||
|
cat /tmp/serial.log || echo "No serial log available" |
||||||
|
|
||||||
|
echo "=== Trying to connect with old credentials ===" |
||||||
|
sshpass -p 'rootpass123' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=5 -p 2222 root@localhost \ |
||||||
|
'journalctl -n 100' 2>/dev/null || echo "Could not connect with old credentials" |
||||||
|
|
||||||
|
echo "=== Trying to connect with new credentials ===" |
||||||
|
sshpass -p 'newpass123' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=5 -p 2222 ${{ matrix.user }}@localhost \ |
||||||
|
'journalctl -n 100' 2>/dev/null || echo "Could not connect with new credentials" |
||||||
|
|
||||||
|
- name: Shutdown VM |
||||||
|
if: always() |
||||||
|
run: | |
||||||
|
# Try graceful shutdown with new credentials first (if new system is installed) |
||||||
|
sshpass -p 'newpass123' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=5 -p 2222 ${{ matrix.user }}@localhost \ |
||||||
|
'sudo poweroff' 2>/dev/null || true |
||||||
|
|
||||||
|
# Also try with old credentials (if still on old system) |
||||||
|
sshpass -p 'rootpass123' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=5 -p 2222 root@localhost \ |
||||||
|
'poweroff' 2>/dev/null || true |
||||||
|
|
||||||
|
sleep 5 |
||||||
|
|
||||||
|
# Force kill QEMU if still running |
||||||
|
sudo pkill qemu-system-x86_64 || true |
||||||
|
|
||||||
|
- name: Upload logs as artifacts |
||||||
|
if: always() |
||||||
|
uses: actions/upload-artifact@v4 |
||||||
|
with: |
||||||
|
name: test-logs-v${{ matrix.version }}-${{ matrix.mirror }}-ethx${{ matrix.ethx }}-${{ matrix.user }}-nc${{ matrix.network_console }} |
||||||
|
path: | |
||||||
|
/tmp/debi-output.log |
||||||
|
/tmp/serial.log |
||||||
|
if-no-files-found: warn |
||||||
Loading…
Reference in new issue