Skip to content

ci(vm::ssh-action): set -fex #30

ci(vm::ssh-action): set -fex

ci(vm::ssh-action): set -fex #30

Workflow file for this run

name: DEV virtual machine
# auto-task.start-build-time = ?
env:
DEBIAN_FRONTEND: noninteractive
on:
# schedule:
# - cron: '0 11 28 */2 *'
push:
paths:
- .github/workflows/dev_vm.yml
jobs:
build:
runs-on: ubuntu-latest
env:
DEV_DIR: assets/dev-vm
defaults:
run:
shell: zsh --pipefail -fex {0}
steps:
- name: install zsh
shell: sh -e {0}
run: ${{ vars.INSTALL_ZSH }}
- uses: actions/checkout@v4
- name: download qemu image
env:
url: "https://cdimage.debian.org/cdimage/cloud/sid/daily/latest/debian-sid-nocloud-amd64-daily.tar.xz"
run: |
sudo apt update
apt_install() {
sudo apt-get install -y $*
}
apt_install aria2
apt_install qemu-system-x86 systemd-container &
aria2c -s5 -x5 -k1m --no-conf -o disk.txz $url
tar --use-compress-program='xz -T0 -dv' -xf disk.txz
- name: get start offset of rootfs partition
id: get_start_offset
run: |
fdisk_cmd=(
sudo env LANG=C /sbin/fdisk --list disk.raw
)
awk_cmd=(
busybox awk
'/([0-9]+[[:space:]]+){3,}[0-9]+(\.[0-9]+)?G/ {
print($2)
}'
)
fdisk_output=$(
$fdisk_cmd
)
integer start=$(
print $fdisk_output | $awk_cmd
)
print -R "start=$((start * 512))" >> $GITHUB_OUTPUT
- name: apt fix-broken
run: |
while {! sudo apt-get install -f} {
sleep 1
}
- name: mount rootfs partition
run: |
mkdir -p rootfs
sudo mount -o loop,offset=${{steps.get_start_offset.outputs.start}} ./disk.raw rootfs
- name: generate local ssh-key
run: |
key=vm.ed25519
ssh-keygen -t ed25519 -f $key -N ""
ssh_client_d=rootfs/root/.ssh
for i ($ssh_client_d) {
sudo install -Dm600 ${key}.pub $i/authorized_keys
sudo chmod 700 -v $i
}
- name: run vm rootfs as container
run: |
sudo rm -vf rootfs/etc/resolv.conf
for i (zsh busybox) {
sudo cp -vf /usr/local/bin/$i rootfs/bin/
}
uuu_keyring=/usr/share/keyrings/ubuntu-archive-keyring.gpg
if [[ -e $uuu_keyring ]] {
sudo cp -vf $uuu_keyring rootfs$uuu_keyring
}
sudo cp -vf ${{env.DEV_DIR}}/systemd/* rootfs/etc/systemd/system/
single_arg=$(<<'CTR_ARG'
apt update
apt-get install -y ifupdown parted
printf "%s\n" "auto enp0s2" "iface enp0s2 inet dhcp" >/etc/network/interfaces.d/dhcp.conf
ssh-keygen -A
printf "%s\n" "TCPKeepAlive yes" "ClientAliveInterval 100" "ClientAliveCountMax 36" >> /etc/ssh/sshd_config.d/keep-alive.conf
chsh -s /bin/zsh
cd /etc/default/grub.d/ || exit 1
print -R 'GRUB_TIMEOUT=1' > 15_timeout.cfg
print -R 'GRUB_TERMINAL="serial"' > 40_serial.cfg
CTR_ARG
)
sudo systemd-nspawn -D rootfs zsh -fexc "$single_arg"
sudo umount -lvf rootfs
- name: install virtiofsd
env:
url: "https://gitlab.com/virtio-fs/virtiofsd/uploads/2cf9068046720699531407101f2bcb60/virtiofsd-v1.10.1.zip"
file: "target/x86_64-unknown-linux-musl/release/virtiofsd"
run: |
curl -Lo v.zip $url
unzip -o v.zip
sudo install -Dm755 $file /usr/libexec/virtiofsd
- name: run vm
run: |
qemu-img create -f qcow2 usr.qcow2 5G
qemu-img create -f qcow2 var.qcow2 10G
cp ${{env.DEV_DIR}}/run .
sudo sysctl -w fs.file-max=1000000
# sudo adduser "$(id -un)" kvm
sudo chmod 666 /dev/kvm
tmux new-session -d -s run-vm ./run
# timeout 10 tmux attach-session -r -t run-vm ||:
- name: copy vm ssh config
env:
conf: vm.sshconf
run: |
install -m600 ${{env.DEV_DIR}}/$conf ./$conf
sudo apt-get install -y autossh
autossh -M0 -F vm.sshconf vm echo OK ||:
- name: Disk partitioning and mounting
uses: 2moe/local-ssh-action@v0
with:
host: vm
run: |
set -fexo pipefail
update-grub
systemctl enable media-sd.automount
systemctl start media-sd.mount
ls -lah /media/sd ||:
local -A map=(
vdb usr
vdc var
)
for i (mount umount reboot) {
cp /bin/busybox /tmp/$i
}
for d (vdc vdb) {
value=$map[$d]
parted -s /dev/$d mklabel gpt
parted -s /dev/$d mkpart ${value}-p1 0% 100%
mkfs.ext4 -FL vm-$value /dev/${d}1
mkdir -pv /tmp/$value
mount /dev/${d}1 /tmp/$value
cp -a /$value /tmp
print -R "LABEL=vm-$value /$value ext4 defaults 0 0" >> /etc/fstab
/tmp/umount -lf /tmp/$value ||:
rm -rf /${value}/* ||:
rm -rf /${value}/.* ||:
/tmp/mount /dev/${d}1 /$value || mount /dev/${d}1 /$value
}
lsblk ||:
/sbin/reboot || /tmp/reboot
args: |
-F
vm.sshconf
- name: wait ssh
run: |
sleep 10
for i ({1..100}) {
print $i
case $(ssh -F vm.sshconf vm echo OK ||:) {
(OK) break ;;
(*) sleep 1 ;;
}
}
- uses: 2moe/local-ssh-action@v0
with:
host: vm
run: |
set -fexo pipefail
export DEBIAN_FRONTEND=noninteractive
df -Th
lsblk
ls -lah /media/sd ||:
sed_args=(
-E
-e '/Suites/ s@( sid).*@\1 experimental@'
-e '$a\Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg'
-i.bak /etc/apt/sources.list.d/debian.sources
)
sed $sed_args
printf "%s\n" 'https://cloudflaremirrors.com/debian' >> /etc/apt/mirrors/debian.list
apt update
apt-get install apt-utils whiptail -y
apt-get upgrade -y
apt-get dist-upgrade -fy
apt-get install -y debootstrap systemd-container docker.io
apt-get install -t experimental -y qemu-user-static
apt-get autopurge -y
apt clean
for dir (/root /var /usr) {
dd if=/dev/zero of=$dir/zero bs=1m || {
rm -v /root/zero
}
}
rm -vf /var/lib/apt/lists/*.* ||:
poweroff
args: |
-F
vm.sshconf
- name: pack vm to tar+zstd
run: |
cp -vf /usr/libexec/virtiofsd .
for i (Readme.md connect-to-ssh) {
cp -vf ${{env.DEV_DIR}}/$i .
}
while {lsof disk.raw} {
print wait disk.raw
sleep 1
}
for file (*.qcow2) {
qemu-img convert -O qcow2 $file _$file
ls -lh $file _$file
mv -vf _$file $file
}
qemu-img convert -O qcow2 disk.raw disk.qcow2
qemu-img convert -O raw disk.qcow2 disk.raw
unlink disk.qcow2
files=(
vm.sshconf
vm.ed25519*
run
disk.raw
*.qcow2
virtiofsd
Readme.md
connect-to-ssh
)
sha256sum $files > sha256.txt
files+=sha256.txt
args=(
--use-compress-program='zstdmt --long -18v'
-cf dev-vm_x64.tar.zst
$files
)
tar $args
- name: release
uses: softprops/action-gh-release@v2
with:
fail_on_unmatched_files: true
tag_name: unstable
files: |
*.tar.zst