Skip to content

Commit

Permalink
Basic setup for GitHub Actions
Browse files Browse the repository at this point in the history
  • Loading branch information
zeha committed Nov 12, 2023
1 parent d911a37 commit e5e06db
Show file tree
Hide file tree
Showing 14 changed files with 436 additions and 320 deletions.
21 changes: 21 additions & 0 deletions .github/workflows/shellcheck.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: shellcheck
on: [pull_request]
jobs:

shellcheck:
name: runner / shellcheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: shellcheck
uses: reviewdog/action-shellcheck@v1
with:
github_token: ${{ secrets.github_token }}
reporter: github-pr-review
path: "."
pattern: |
chroot-script
grml-debootstrap
config
tests/shellcheck-stub-debootstrap-variables
check_all_files_with_shebangs: "false"
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
*.box
packer_cache
*_output
qemu.img
tests/dgoss
tests/goss
15 changes: 0 additions & 15 deletions .travis.yml

This file was deleted.

59 changes: 59 additions & 0 deletions tests/build-vm-and-test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# Install an already built grml-debootstrap.deb in docker and use it to
# build a test VM image. Then run this VM image in qemu and check if it
# boots.

set -eu -o pipefail

if [ -z "${1:-}" ] || [ "${1:-}" == "--help" ] || [ "${1:-}" == "help" ]; then
echo "Usage: $0 setup"
echo " then: $0 run"
echo "WARNING: $0 is potentially dangerous and may destroy the host system and/or any data."
exit 0
fi

if [ "$1" == "setup" ]; then
set -x
[ -x ./tests/goss ] || curl -fsSL https://goss.rocks/install | GOSS_DST="$(pwd)/tests" sh
sudo apt-get update
sudo apt-get -y install qemu-system-x86 kpartx python3-pexpect python3-serial
# TODO: docker.io
exit 0
fi

if [ "$1" != "run" ]; then
echo "$0: unknown parameters, see --help"
exit 1
fi

if [ ! -d ./tests ]; then
echo "$0: Started from incorrect working directory"
exit 1
fi

set -x

# Debian version on which grml-debootstrap will *run*
HOST_RELEASE="${HOST_RELEASE:-bookworm}"

# Debian version to install using grml-debootstrap
RELEASE="${RELEASE:-bookworm}"

TARGET="${TARGET:-qemu.img}"

DEB_NAME=$(ls ./grml-debootstrap*.deb || true)
if [ -z "$DEB_NAME" ]; then
echo "$0: No grml-debootstrap*.deb found, aborting"
exit 1
fi

# we need to run in privileged mode to be able to use loop devices
docker run --privileged -v "$(pwd)":/code --rm -i debian:"$HOST_RELEASE" \
bash -c 'TERM='"$TERM"' cd /code && ./tests/docker-install-deb.sh '"$DEB_NAME"' && ./tests/docker-build-vm.sh '"$(id -u)"' '"/code/$TARGET"' '"$RELEASE"

# run tests from inside Debian system
./tests/test-vm.sh "$PWD/$TARGET" "$RELEASE"

# EOF
44 changes: 44 additions & 0 deletions tests/docker-build-deb.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# Build a grml-debootstrap.deb.
# To be run inside docker, as this script assumes it can modify the running OS.

set -eu -o pipefail
set -x

if [ "${1:-}" != "--autobuild" ]; then
echo "$0: Only intended for CI scenarios, will destroy source files and modify running OS."
exit 1
fi
BUILD_NUMBER="${2:-}"
if [ -z "$BUILD_NUMBER" ]; then
echo "$0: missing build number in arguments"
exit 1
fi

apt-get update
apt-get install --no-install-recommends -y build-essential devscripts equivs

SOURCEDIR=$PWD

cd /tmp
mk-build-deps -ir -t 'apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends -y' "$SOURCEDIR"/debian/control

dpkg-source -b "$SOURCEDIR"
dpkg-source -x ./*.dsc builddir
cd builddir

OLD_VERSION=$(dpkg-parsechangelog -SVersion)

cat > debian/changelog <<EOT
grml-debootstrap (${OLD_VERSION}+autobuild${BUILD_NUMBER}) UNRELEASED; urgency=medium
* Automated Build
-- Automated Build <builder@localhost> $(date -R)
EOT

dpkg-buildpackage -b --no-sign

mv ../*deb "$SOURCEDIR"/
31 changes: 31 additions & 0 deletions tests/docker-build-vm.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# Use an already installed grml-debootstrap to build a VM image, then
# run it in qemu. Installs goss inside the VM.

set -eu -o pipefail

if [ "$#" -ne 3 ]; then
echo "$0: Invalid arguments"
echo "Expect: $0 HOST_UID TARGET RELEASE"
exit 1
fi
HOST_UID="$1"
TARGET="$2"
RELEASE="$3"

echo " ****************************************************************** "
echo " * Running grml-debootstrap"

grml-debootstrap \
--force \
--vmfile \
--vmsize 3G \
--target "$TARGET" \
--bootappend "console=ttyS0,115200 console=tty0 vga=791" \
--password grml \
--release "$RELEASE" \
--hostname "$RELEASE"

chown "$HOST_UID" "$TARGET"
17 changes: 17 additions & 0 deletions tests/docker-install-deb.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# Install an already built grml-debootstrap.deb.
# Wrapper around apt-get install for usage inside docker.

set -eu -o pipefail

if [ "$#" -ne 1 ]; then
echo "$0: Invalid arguments"
echo "Expect: $0 DEB_NAME"
exit 1
fi
DEB_NAME="$1"

apt-get update
apt-get -y install "$DEB_NAME"
31 changes: 31 additions & 0 deletions tests/gha-test-build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# Entrypoint for GitHub Actions to build a grml-debootstrap.deb, run it,
# and build a VM image and test that.
# Will modify running OS.

set -eu -o pipefail
set -x

if [ -z "${CI:-}" ] ; then
echo "Running outside of CI pipeline."
exit 1
fi

# Debian version on which grml-debootstrap will *run*
HOST_RELEASE="${HOST_RELEASE:-bookworm}"
export HOST_RELEASE

echo " ****************************************************************** "
echo " * Building grml-debootstrap for debian ${HOST_RELEASE}"
docker run --privileged -v "$(pwd)":/code --rm -i debian:"$HOST_RELEASE" \
bash -c 'TERM='"$TERM"' cd /code && ./tests/docker-build-deb.sh --autobuild '"$GITHUB_RUN_NUMBER"

echo " ****************************************************************** "
echo " * Setting up VM build environment"
./tests/build-vm-and-test.sh setup

echo " ****************************************************************** "
echo " * Running VM build test"
./tests/build-vm-and-test.sh run
File renamed without changes.
105 changes: 105 additions & 0 deletions tests/serial-console-connection
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#!/usr/bin/env python
import argparse
import pexpect
import serial
import sys
import time
from pexpect import fdpexpect, TIMEOUT

parser = argparse.ArgumentParser(description='Connect to serial console ' +
'to execute stuff')
parser.add_argument('--port', required=True,
help='serial console device to connect ' +
'to (e.g. /dev/pts/X)')
parser.add_argument('--hostname', default="buster",
help='hostname of the system for login process ' +
'(default: buster)')
parser.add_argument('--user', default="root",
help='user name to use for login (default: root)')
parser.add_argument('--password', default="grml",
help='password for login (default: grml)')
parser.add_argument('--tries', default="12", type=int,
help='Number of retries for finding the login prompt')
parser.add_argument('--poweroff', action="store_true", default=False,
help='send "poweroff" command after all other commands')
parser.add_argument('command', nargs='+',
help='command to execute after logging in')



def print_ser_lines(ser):
for line in ser.readlines():
print("<<", line) # line will be a binary string


def write_ser_line(ser, text):
print(">>", text)
ser.write(("%s\n" % text).encode())
ser.flush()


def login(ser, hostname, user, password, timeout=5):

child = fdpexpect.fdspawn(ser.fileno())
child.sendline("\n")

try:
child.expect("%s@%s" % (user, hostname), timeout=timeout)
return
except:
pass

print("Waiting for login prompt...")
child.expect("%s login:" % hostname, timeout=timeout)
print("Logging in...")
write_ser_line(ser, user)
time.sleep(1)
write_ser_line(ser, password)
time.sleep(1)

print("Waiting for shell prompt...")
child.expect("%s@%s" % (user, hostname), timeout=timeout)


def main():
args = parser.parse_args()
hostname = args.hostname
password = args.password
port = args.port
user = args.user
commands = args.command

ser = serial.Serial(port, 115200)
ser.flushInput()
ser.flushOutput()

success = False
for i in range(args.tries):
try:
print("Logging into %s via serial console [try %s]" % (port, i))
login(ser, hostname, user, password)
success = True
break
except Exception as except_inst:
print("Login failure (try %s):" % (i, ), except_inst, file=sys.stderr)
time.sleep(5)

if success:
write_ser_line(ser, "")
ser.timeout = 5
print_ser_lines(ser)
print("Running commands...")
for command in commands:
write_ser_line(ser, command)
print_ser_lines(ser)
if args.poweroff:
print("Sending final poweroff command...")
write_ser_line(ser, "poweroff")
ser.flush()
# after poweroff, the serial device will probably vanish. do not attempt reading from it anymore.

if not success:
sys.exit(1)

if __name__ == "__main__":
main()

0 comments on commit e5e06db

Please sign in to comment.