Skip to content

Publish GardenLinux Images #54

Publish GardenLinux Images

Publish GardenLinux Images #54

name: Publish GardenLinux Image
on:
schedule:
# Run weekly on Sundays at 00:00 UTC
- cron: '0 0 * * 0'
workflow_dispatch:
jobs:
check-release:
runs-on: ubuntu-latest
outputs:
latest_version: ${{ steps.get-latest.outputs.latest_version }}
should_publish: ${{ steps.check-published.outputs.should_publish }}
steps:
- name: Get Latest GardenLinux Release
id: get-latest
run: |
LATEST_RELEASE=$(curl -s https://api.github.com/repos/gardenlinux/gardenlinux/releases/latest | jq -r '.tag_name')
echo "Latest GardenLinux release: $LATEST_RELEASE"
echo "latest_version=$LATEST_RELEASE" >> $GITHUB_OUTPUT
- name: Check if Version Already Published
id: check-published
run: |
LATEST_VERSION="${{ steps.get-latest.outputs.latest_version }}"
# Check if the image already exists in ghcr.io by attempting to pull the manifest
if docker manifest inspect ghcr.io/${{ github.repository_owner }}/os-images/gardenlinux-amd64:$LATEST_VERSION > /dev/null 2>&1; then
echo "Version $LATEST_VERSION already published, skipping"
echo "should_publish=false" >> $GITHUB_OUTPUT
else
echo "New version $LATEST_VERSION found, will publish"
echo "should_publish=true" >> $GITHUB_OUTPUT
fi
publish:
needs: check-release
if: needs.check-release.outputs.should_publish == 'true'
permissions:
contents: read
packages: write
runs-on: ubuntu-latest
strategy:
matrix:
arch: [ "arm64", "amd64" ]
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Setup ORAS
uses: oras-project/setup-oras@v1
- name: Set Version and Artifact URLs
id: read-config
run: |
OS_VERSION="${{ needs.check-release.outputs.latest_version }}"
echo "OS_VERSION=$OS_VERSION" >> $GITHUB_ENV
# Fetch release assets to find the correct artifact filenames
ASSETS=$(curl -s "https://api.github.com/repos/gardenlinux/gardenlinux/releases/tags/$OS_VERSION" | jq -r '.assets[].name')
# Find KVM artifact for this architecture
KVM_ASSET=$(echo "$ASSETS" | grep -E "^kvm-gardener_prod-${{ matrix.arch }}-.*\.tar\.xz$" | head -1)
if [ -z "$KVM_ASSET" ]; then
echo "Error: Could not find KVM artifact for ${{ matrix.arch }}"
exit 1
fi
GARDENLINUX_KVM_ARTIFACT_URL="https://github.com/gardenlinux/gardenlinux/releases/download/$OS_VERSION/$KVM_ASSET"
echo "GARDENLINUX_KVM_ARTIFACT_URL=$GARDENLINUX_KVM_ARTIFACT_URL" >> $GITHUB_ENV
# Find Metal PXE artifact for this architecture (optional - may not exist for arm64)
METAL_ASSET=$(echo "$ASSETS" | grep -E "^metal-gardener_prod_pxe-${{ matrix.arch }}-.*\.tar\.xz$" | head -1)
if [ -z "$METAL_ASSET" ]; then
echo "Warning: Could not find Metal artifact for ${{ matrix.arch }}, skipping Metal artifacts"
echo "HAS_METAL_ARTIFACT=false" >> $GITHUB_ENV
else
GARDENLINUX_METAL_ARTIFACT_URL="https://github.com/gardenlinux/gardenlinux/releases/download/$OS_VERSION/$METAL_ASSET"
echo "GARDENLINUX_METAL_ARTIFACT_URL=$GARDENLINUX_METAL_ARTIFACT_URL" >> $GITHUB_ENV
echo "HAS_METAL_ARTIFACT=true" >> $GITHUB_ENV
fi
echo "KVM URL: $GARDENLINUX_KVM_ARTIFACT_URL"
if [ -n "$METAL_ASSET" ]; then
echo "Metal URL: $GARDENLINUX_METAL_ARTIFACT_URL"
else
echo "Metal URL: (not available for ${{ matrix.arch }})"
fi
- name: Download and Extract Gardenlinux KVM Artifact
run: |
curl -L ${{ env.GARDENLINUX_KVM_ARTIFACT_URL }} -o gardenlinux.tar.xz
tar -xf gardenlinux.tar.xz
echo "Extracted contents:"
ls -la
- name: Download and Extract Gardenlinux Metal Artifact
if: env.HAS_METAL_ARTIFACT == 'true'
run: |
# Download the outer tarball
curl -L ${{ env.GARDENLINUX_METAL_ARTIFACT_URL }} -o gardenlinux-metal.tar.xz
tar -xf gardenlinux-metal.tar.xz
# Extract the nested tarball to get the initrd, vmlinuz, and root.squashfs files
NESTED_TARBALL=$(find . -name "*pxe.tar.gz")
tar -xzf $NESTED_TARBALL
- name: Create Config JSON
run: |
if [ "${{ matrix.arch }}" == "arm64" ]; then
echo "{\"commandLine\": \"gl.url=/dev/disk/by-id/virtio-machineboot gl.live=1 gl.ovl=/:tmpfs console=tty0 console=ttyAMA0,115200 earlyprintk=ttyAMA0,115200 consoleblank=0 cgroup_enable=memory swapaccount=1 ignition.firstboot=1 ignition.platform.id=qemu\", \"os-release\": \"$OS_VERSION\", \"arch\": \"${{ matrix.arch }}\"}" > config.json
fi
if [ "${{ matrix.arch }}" == "amd64" ]; then
echo "{\"commandLine\": \"gl.url=/dev/disk/by-id/virtio-machineboot gl.live=1 gl.ovl=/:tmpfs console=tty0 console=ttyS0,115200 earlyprintk=ttyS0,115200 consoleblank=0 cgroup_enable=memory swapaccount=1 ignition.firstboot=1 ignition.platform.id=qemu\", \"os-release\": \"$OS_VERSION\", \"arch\": \"${{ matrix.arch }}\"}" > config.json
fi
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Push Image with ORAS (Version Tag)
run: |
# Find the .raw file dynamically (handles varying folder structures)
KVM_RAW_FILE=$(find . -name "*.raw" -type f | head -1)
if [ -z "$KVM_RAW_FILE" ]; then
echo "Error: Could not find .raw file after extraction"
exit 1
fi
echo "Found KVM raw file: $KVM_RAW_FILE"
# Build the oras push command with required KVM artifact
ORAS_ARGS="$KVM_RAW_FILE:application/vnd.ironcore.image.rootfs.v1alpha1.rootfs"
# Add Metal artifacts if available
if [ "${{ env.HAS_METAL_ARTIFACT }}" == "true" ]; then
ORAS_ARGS="$ORAS_ARGS root.squashfs:application/vnd.ironcore.image.squashfs.v1alpha1.squashfs"
ORAS_ARGS="$ORAS_ARGS initrd:application/vnd.ironcore.image.initramfs.v1alpha1.initramfs"
ORAS_ARGS="$ORAS_ARGS vmlinuz:application/vnd.ironcore.image.vmlinuz.v1alpha1.vmlinuz"
fi
oras push ghcr.io/${{ github.repository_owner }}/os-images/gardenlinux-${{ matrix.arch }}:$OS_VERSION \
$ORAS_ARGS \
--config config.json:application/vnd.ironcore.image.config.v1alpha1+json
- name: Push Image with ORAS (Latest Tag)
run: |
oras tag ghcr.io/${{ github.repository_owner }}/os-images/gardenlinux-${{ matrix.arch }}:$OS_VERSION latest