OpenWrt master build #72
This file contains 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: OpenWrt master build | |
on: | |
push: | |
branches: | |
- master | |
schedule: | |
- cron: '0 15 * * *' | |
env: | |
OPENWRT_VERSION: master | |
jobs: | |
build: | |
name: Build | |
runs-on: ubuntu-latest | |
services: | |
registry: | |
image: registry:2 | |
ports: | |
- 5000:5000 | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Set up QEMU | |
uses: docker/setup-qemu-action@v3 | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v3 | |
with: | |
driver-opts: network=host # Important to access local Docker registry | |
- name: Login into Docker Hub | |
uses: docker/login-action@v3 | |
with: | |
username: ${{ secrets.DOCKERHUB_USERNAME }} | |
password: ${{ secrets.DOCKERHUB_TOKEN }} | |
- name: Build Docker image | |
uses: docker/build-push-action@v6 | |
env: | |
DOCKER_BUILD_RECORD_UPLOAD: false | |
with: | |
context: . | |
push: true | |
provenance: false | |
platforms: | | |
linux/x86_64 | |
linux/arm64 | |
build-args: | | |
OPENWRT_VERSION=${{ env.OPENWRT_VERSION }} | |
BUILDKIT_MULTI_PLATFORM=1 | |
tags: | | |
albrechtloh/openwrt-docker:ci-openwrt-master-snapshot | |
localhost:5000/local/openwrt-docker:latest | |
- name: Inspect | |
run: | | |
docker buildx imagetools inspect localhost:5000/local/openwrt-docker:latest | |
- name: Build and export | |
uses: docker/build-push-action@v6 | |
env: | |
DOCKER_BUILD_SUMMARY: false | |
DOCKER_BUILD_RECORD_UPLOAD: false | |
with: | |
context: . # TODO: Just for testing | |
tags: openwrt-docker:latest | |
build-args: OPENWRT_VERSION=${{ env.OPENWRT_VERSION }} | |
allow: security.insecure,network.host | |
outputs: type=docker,dest=/tmp/openwrt-docker-image.tar | |
- name: Upload artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: OpenWrt Docker Image | |
path: /tmp/openwrt-docker-image.tar | |
- name: Login to Weidmueller wmucdev | |
uses: docker/login-action@v3 | |
with: | |
registry: wmucdev.azurecr.io | |
username: ${{ secrets.WMUCDEV_USERNAME }} | |
password: ${{ secrets.WMUCDEV_TOKEN }} | |
- name: Create Weidmueller u-OS app | |
id: create_u-os-app | |
run: | | |
# uc-aom-packager accept only version that has to be greater than the previous one. Lets use the datetime to ensure that. | |
DATETIME=$(date "+%Y%m%d%H%M%S") | |
# uc-aom-packager allow only decimal numbers as version number for an unkonwn reason | |
# see https://github.com/weidmueller/uc-addon/blob/main/uc-manifest.schema-doc.md#version) | |
# So lets convert the git hash into a decimal value | |
GIT_HASH=`git rev-parse --short HEAD` | |
GIT_HASH_DECIMAL=$((16#$GIT_HASH)) | |
# Create app version | |
#APP_VERSION=$OPENWRT_VERSION.$DATETIME-$GIT_HASH_DECIMAL | |
APP_VERSION=0.0.0.$DATETIME-$GIT_HASH_DECIMAL # TODO just for SNAPSHOT | |
echo "***** Create manifest from template *****" | |
mv u-os-app/manifest.json.template u-os-app/manifest.json | |
sed -i 's/APPVERSION_TO_INSERT/'"$APP_VERSION"'/g' u-os-app/manifest.json | |
cat u-os-app/manifest.json | grep version | |
echo "***** Run uc-aom-packager to create the u-OS app *****" | |
# uc-aom-packager accepts only multiarch images. "--build-arg BUILDKIT_MULTI_PLATFORM=1" has to set to ensure that. | |
# uc-aom-packager needs to Docker registry credentials in a clear text file. Because of security concerns we use a local registry without credentials here. | |
docker run --rm --network=host --pull=always \ | |
--mount src=$(pwd)/u-os-app,target=/tmp/u-os-app-openwrt,type=bind wmucdev.azurecr.io/u-control/uc-aom-packager:0 \ | |
uc-aom-packager push \ | |
-m /tmp/u-os-app-openwrt \ | |
-s /tmp/u-os-app-openwrt/source-credentials.json \ | |
-t /tmp/u-os-app-openwrt/target-credentials.json \ | |
-v | |
echo "***** Create SWU app file*****" | |
docker run --rm --network=host --pull=always \ | |
--mount src=$(pwd)/u-os-app,target=/tmp/u-os-app-openwrt,type=bind wmucdev.azurecr.io/u-control/uc-aom-packager:0 \ | |
uc-aom-packager \ | |
export \ | |
-t /tmp/u-os-app-openwrt/target-credentials.json \ | |
--version $APP_VERSION \ | |
-o /tmp/u-os-app-openwrt/u-os-app-openwrt_$APP_VERSION.swu \ | |
-v | |
find u-os-app/ | |
- name: Archive artifacts (OpenWrt u-OS app) | |
if: always() && steps.create_u-os-app.outcome == 'success' | |
uses: actions/upload-artifact@v4 | |
with: | |
name: OpenWrt u-OS app | |
path: u-os-app/u-os-app-openwrt_*.swu/linux-arm64/*.swu | |
if-no-files-found: error | |
sbom: | |
name: SBOM generation | |
needs: build | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Generate alpine SBOM | |
uses: anchore/sbom-action@v0 | |
with: | |
image: albrechtloh/openwrt-docker:ci-openwrt-master-snapshot | |
upload-artifact: false | |
format: cyclonedx-json | |
output-file: alpine_sbom.json | |
- name: Prepare OpenWrt rootfs | |
run: | | |
# Run OpenWrt container for some time to install additional IPKs | |
set +e # Enable that the next command can fail | |
timeout --preserve-status 30 docker compose up | |
set -e # Revert set +e | |
# Get image from volume | |
sudo find /var/lib/docker/volumes/ | |
IMAGE=$(sudo cat /var/lib/docker/volumes/openwrt-docker_data/_data/current_version) | |
echo $IMAGE | |
# Mount volume | |
wget https://raw.githubusercontent.com/AlbrechtL/openwrt-docker/refs/heads/master/src/mount_openwrt_squashfs_combined.sh | |
chmod +x mount_openwrt_squashfs_combined.sh | |
sudo ./mount_openwrt_squashfs_combined.sh "/var/lib/docker/volumes/openwrt-docker_data/_data/${IMAGE}" $(arch) | |
- name: Generate OpenWrt SBOM | |
uses: anchore/sbom-action@v0 | |
with: | |
path: /mnt | |
upload-artifact: false | |
format: cyclonedx-json | |
output-file: openwrt_sbom.json | |
- name: Generate web-frontend SBOM | |
uses: anchore/sbom-action@v0 | |
with: | |
path: web-frontend | |
upload-artifact: false | |
format: cyclonedx-json | |
output-file: web-frontend_sbom.json | |
- name: Generate web-backend SBOM | |
uses: anchore/sbom-action@v0 | |
with: | |
path: web-backend | |
upload-artifact: false | |
format: cyclonedx-json | |
output-file: web-backend_sbom.json | |
- name: Archive artifacts (SBOMs) | |
uses: actions/upload-artifact@v4 | |
with: | |
name: Software Bill of Material (SBOM) | |
path: ./*.json | |
if-no-files-found: error | |
test: | |
name: Test | |
runs-on: ubuntu-latest | |
needs: build | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Download artifact | |
uses: actions/download-artifact@v4 | |
with: | |
name: OpenWrt Docker Image | |
path: . | |
- name: Install VMs | |
run: | | |
set -x | |
sudo snap install multipass --edge # Edge is necessary to get 1.15 dev because of networks support | |
sudo chmod a+w /var/snap/multipass/common/multipass_socket # Fix 'multipass socket access denied' | |
multipass find | |
# Set up some bridges for the VMs | |
sudo ip link add lannetvm type bridge | |
sudo ip link add wannetvm type bridge | |
sudo ip link set dev lannetvm up | |
sudo ip link set dev wannetvm up | |
ip addr | |
# We need to disable the firewall otherwise the tap devices are not working properly | |
sudo ufw disable | |
# Start VMs | |
# Multipass and the OpenWrt container are using the same MAC QUI 52:54:00 which creates error. Let's use differnet MAC addresses here | |
multipass launch docker --network name=wannetvm,mac=06:00:00:11:22:33 --network name=lannetvm,mac=06:00:00:44:55:66 --name router-vm | |
multipass mount $GITHUB_WORKSPACE router-vm | |
multipass launch --network wannetvm --name wan-vm | |
multipass launch --network lannetvm --name lan-vm | |
- name: Show VM and and environments variables | |
run: | | |
export | |
multipass exec router-vm -- lsb_release -a | |
multipass info | |
- name: Load image | |
run: | | |
multipass exec router-vm -- docker load --input openwrt-docker-image.tar | |
multipass exec router-vm -- docker image ls -a | |
- name: Prepare VMs | |
run: | | |
# By default portainer is running at port 9000. But we need port 9000 | |
multipass exec router-vm -- docker stop portainer | |
# Install python | |
multipass exec router-vm -- sudo apt-get -y install python3-pip python-is-python3 | |
# Install everthing for pytest | |
multipass exec router-vm -- find . | |
#multipass exec router-vm -- export PATH=$PATH:~/.local/bin # not working | |
multipass exec router-vm -- pip install -r test/requirements.txt | |
echo '******** router-vm IPs ********' | |
multipass exec router-vm -- ip addr | |
# Prepare WAN VM | |
echo '******** wan-vm IPs ********' | |
# Add IP address | |
multipass exec wan-vm -- sudo ip addr add 192.168.22.1/24 dev ens4 | |
multipass exec wan-vm -- ip addr | |
# Install DHCP server | |
multipass exec wan-vm -- sudo sh -c 'apt-get update && apt-get install -y isc-dhcp-server && echo "default-lease-time 600;\nmax-lease-time 7200;\nsubnet 192.168.22.0 netmask 255.255.255.0 {\n range 192.168.22.100 192.168.22.200;\n option routers 192.168.22.1;\n option domain-name-servers 8.8.8.8, 8.8.4.4;\n option domain-name \"example.org\";\n}" > /etc/dhcp/dhcpd.conf && systemctl enable isc-dhcp-server && systemctl restart isc-dhcp-server' | |
multipass exec wan-vm -- cat /etc/dhcp/dhcpd.conf | |
# Enable NAT | |
multipass exec wan-vm -- sudo modprobe iptable_nat | |
multipass exec wan-vm -- sudo iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE | |
multipass exec wan-vm -- sudo sysctl -w net.ipv4.ip_forward=1 | |
# Prepare LAN VM | |
echo '******** lan-vm IPs ********' | |
multipass exec lan-vm -- sudo ip addr add 172.31.1.2/24 dev ens4 | |
multipass exec lan-vm -- sudo ip addr add 172.31.22.2/24 dev ens4 | |
multipass exec lan-vm -- ip addr | |
# Double check if virtual networks are working | |
echo '******** host IPs ********' | |
ip addr | |
sudo ufw status | |
echo '******** router-vm IPs ********' | |
multipass exec router-vm -- sudo ip addr add 192.168.22.99/24 dev ens4 | |
multipass exec router-vm -- sudo ip addr add 172.31.22.99/24 dev ens5 | |
multipass exec router-vm -- ip addr | |
echo '******** Test connection between router-vm, lan-vm and wan-vm ********' | |
multipass exec router-vm -- ping -c 1 192.168.22.1 # to wan-vm | |
multipass exec router-vm -- ping -c 1 172.31.22.2 # to lan-vm | |
- name: Prepare tests | |
run: | | |
# Use local image instead of hub.docker.com | |
sed -i 's/image: albrechtloh\/openwrt-docker:latest/image: openwrt-docker/g' test/tests/docker-compose.yml.template | |
cat test/tests/docker-compose.yml.template | |
- name: Run tests | |
run: | | |
cat test/tests/docker-compose.yml.template | |
# Run pytest | |
multipass exec router-vm -- sh -c 'cd test/ && ~/.local/bin/pytest -v -s --html=report.html --self-contained-html' | |
- name: Archive test report | |
if: always() | |
uses: actions/upload-artifact@v4 | |
with: | |
name: Test report | |
path: test/*.html | |
if-no-files-found: error | |
publish: | |
name: Publish | |
needs: test | |
runs-on: ubuntu-latest | |
steps: | |
- name: Login into Docker Hub | |
uses: docker/login-action@v3 | |
with: | |
username: ${{ secrets.DOCKERHUB_USERNAME }} | |
password: ${{ secrets.DOCKERHUB_TOKEN }} | |
- name: Tag image at Docker Hub | |
run: | | |
docker buildx imagetools create \ | |
--tag albrechtloh/openwrt-docker:openwrt-master-snapshot \ | |
albrechtloh/openwrt-docker:ci-openwrt-master-snapshot |