Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: build
run-name: Create patched ISO images

on:
# allow the workflow to be called from another workflow
workflow_call:
# allow the workflow to be run from the Github Actions UI
workflow_dispatch:
# trigger the workflow when a 'push' event happens to any branch except the main branch
push:
branches:
- '**'
- '!main'

jobs:
# the build job to run the build script
build:
runs-on: ubuntu-latest
steps:
- name: Check out the repository to the runner
uses: actions/checkout@v4
- name: Make the build script executable
run: chmod u+x scripts/build.sh
- name: Install dependent packages
run: sudo apt install -y p7zip-full p7zip-rar genisoimage fakeroot xorriso isolinux binutils squashfs-tools
- name: Run the build script
run: scripts/build.sh
# one set of upload statements for each OS image artifact
- name: Upload the vault-ubuntu-minimal artifact
uses: actions/upload-artifact@v4
with:
name: vault-ubuntu-minimal
path: vault-ubuntu-minimal.iso
32 changes: 32 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: release
run-name: Create a new release

on:
# allow the workflow to be run from the Github Actions UI
workflow_dispatch:
# trigger the workflow run when a 'push' event happens to a tag with semantic versioning
push:
tags:
- "v*.*.*"

jobs:
# call the build job (reuse from earlier workflow)
build:
uses: ./.github/workflows/build.yml
# the release job that will create a new release of all built OS images
release:
needs: build
runs-on: ubuntu-latest
steps:
- name: Check out the repository to the runner
uses: actions/checkout@v4
# one set of statements for each OS image that needs to be downloaded
# and included in the next release
- name: Download the vault-ubuntu-minimal artifact
uses: actions/download-artifact@v4
with:
name: vault-ubuntu-minimal
- name: Create a new release with latest images for all OSes
uses: softprops/action-gh-release@v2
with:
files: vault-ubuntu-minimal.iso
104 changes: 104 additions & 0 deletions scripts/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#! /bin/bash

# function to detect the environment and return an appropriate file name
assign_file_name () {
# check if it is a CI/CD environment like Github Actions
if [ -v CI ]; then
FILENAME="$1.iso"
else
IS_GIT=$(git rev-parse --is-inside-work-tree 2>&1)
# check if it is a git repository like when in local development
if [ $IS_GIT ]; then
GIT_COMMIT=$(git rev-parse --short HEAD)
DATE=$(date -u '+%Y%m%d')
FILENAME="$1-$DATE.$GIT_COMMIT.iso"
fi
fi
echo $FILENAME
}

# function to create builds for all linux operating systems in scope
build_linux_oses () {
# array of URLs pointing to the base images of the operating system being handled
# give official, downloadable URLs, preferably from the same source as provided in the README
declare -a LINUXIMAGES=(
"https://releases.ubuntu.com/22.04.5/ubuntu-22.04.5-live-server-amd64.iso"
)

# array of directory names as present in this project
# this is used to copy and use the cloud-init config data
declare -a LINUXOSDIRS=(
"ubuntu-server-22-04-5"
)

# array of patched operating system names
# preferably in the `vault-<base-operating-system>` format
declare -a VAULTLINUXOSES=(
"vault-ubuntu-minimal"
)

# get lengths of above mentioned arrays
IMAGESLENGTH=${#LINUXIMAGES[@]}
OSESLENGTH=${#LINUXOSDIRS[@]}
VAULTSLENGTH=${#VAULTLINUXOSES[@]}

# perform a check to confirm that all arrays have equal lengths
# if not, exit with an appropriate message
if [ $IMAGESLENGTH -ne $OSESLENGTH ] || [ $OSESLENGTH -ne $VAULTLINUXOSES ] || [ $IMAGESLENGTH -ne $VAULTLINUXOSES ]; then
echo "IMAGESLENGTH, OSESLENGTH, VAULTLINUXOSES are not of equal lengths. Recheck array entries."
exit 1
fi

# iterate through the list of operating systems and patch them with data from the cloud-init config files
for (( i=0; i<${IMAGESLENGTH}; i++ ));
do
TARGETFILENAME=$(assign_file_name "${VAULTLINUXOSES[$i]}")
echo "Creating patched OS: $TARGETFILENAME..."
# download the base OS image
curl -X GET -OL ${LINUXIMAGES[$i]}
SOURCEISO=${LINUXIMAGES[$i]##*/}
# extract the downloaded ISO image to the iso/ directory
7z x -y $SOURCEISO -oiso

# copy the cloud-init configuration files into the iso/nocloud directory
mkdir -p iso/nocloud
cp "${LINUXOSDIRS[$i]}/meta-data" iso/nocloud/
cp "${LINUXOSDIRS[$i]}/user-data" iso/nocloud/

## TODO: think of how this can possibly be extended to
## other OSes. Do the boot kernel parameters change the
## same way? Will we need a if-else tree to do it?

# modify boot related files
sed -i -e 's/---/ autoinstall ---/g' iso/boot/grub/grub.cfg
sed -i -e 's/---/ autoinstall ---/g' iso/boot/grub/loopback.cfg
# modify kernel boot parameters to insert path to cloud-init config
sed -i -e 's,---, ds=nocloud\\;s=/cdrom/nocloud/ ---,g' iso/boot/grub/grub.cfg
sed -i -e 's,---, ds=nocloud\\;s=/cdrom/nocloud/ ---,g' iso/boot/grub/loopback.cfg

# create the final ISO image
xorriso -as mkisofs -r \
-V ${LINUXOSDIRS[$i]} \
-o $TARGETFILENAME \
-J \
-c '/boot.catalog' \
-b '/boot/grub/i386-pc/eltorito.img' \
-no-emul-boot -boot-load-size 4 -boot-info-table --grub2-boot-info \
-eltorito-alt-boot \
-isohybrid-gpt-basdat -isohybrid-apm-hfsplus \
iso/boot iso

FILESIZE=$(stat -c %s $TARGETFILENAME 2>&1)
# verify that the patched iso image file was created properly
if [[ $FILESIZE > 0 ]]; then
printf '%s (%d bytes) ... done!\n' $TARGETFILENAME $FILESIZE
else
printf 'Something went wrong while trying to build %s\n' $TARGETFILENAME
fi

# remove the iso/ directory
sudo rm -rf iso
done
}

build_linux_oses