diff --git a/.github/workflows/build-k3s.yaml b/.github/workflows/build-k3s.yaml index 3d4bd14597b..43fc8b280b9 100644 --- a/.github/workflows/build-k3s.yaml +++ b/.github/workflows/build-k3s.yaml @@ -11,6 +11,12 @@ on: default: 'linux' upload-image: type: boolean + description: 'Build and upload k3s image (only works on arm64 or amd64)' + required: false + default: false + upload-build: + type: boolean + description: 'Upload contents of build/out, used to build the k3s image externally' required: false default: false cache: @@ -45,7 +51,7 @@ jobs: if: inputs.arch == 'arm' uses: docker/setup-qemu-action@v3 with: - platforms: linux/arm/v7 + cache-image: false - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -70,7 +76,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Build K3s Binary Native - if: inputs.arch != 'arm' + if: inputs.arch == 'arm64' || inputs.arch == 'amd64' env: DOCKER_BUILD_SUMMARY: false uses: docker/build-push-action@v6 @@ -122,15 +128,20 @@ jobs: fi - name: Build K3s image - if: inputs.upload-image == true && inputs.os == 'linux' + if: inputs.upload-image == true && inputs.os == 'linux' && (inputs.arch == 'amd64' || inputs.arch == 'arm64') run: ./scripts/package-image - name: "Save K3s image" if: inputs.upload-image == true && inputs.os == 'linux' run: docker image save rancher/k3s -o ./dist/artifacts/k3s-image.tar - + + - name: "Save K3s build" + if: inputs.upload-build == true && inputs.os == 'linux' + run: | + mv ./build/out/data-linux.tar.zst ./dist/artifacts/data-linux${{ env.ARCH_EXT }}.tar.zst + - name: "Upload K3s Artifacts" uses: actions/upload-artifact@v4 with: name: k3s${{ env.ARCH_EXT }} - path: dist/artifacts/k3s* \ No newline at end of file + path: dist/artifacts/ \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000000..876d3d2c916 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,104 @@ +name: K3s Release + +on: + release: + types: [published] + +permissions: + contents: read + packages: read + +jobs: + build-amd64: + name: Build Binary (amd64) + uses: ./.github/workflows/build-k3s.yaml + with: + cache: '' # No cache for release builds + upload-build: true + + build-arm64: + name: Build Binary (arm64) + uses: ./.github/workflows/build-k3s.yaml + with: + arch: arm64 + cache: '' # No cache for release builds + upload-build: true + + build-arm: + name: Build Binary (arm) + uses: ./.github/workflows/build-k3s.yaml + with: + arch: arm + cache: '' # No cache for release builds + upload-build: true + + push-release-image: + name: Build and Push Multi-Arch Image + runs-on: ubuntu-latest + permissions: + packages: write # Needed to push images to GHCR + needs: [build-amd64, build-arm64, build-arm] + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: COnfigure image tags + id: tag_config + run: | + TAG=${GITHUB_REF#refs/tags/} + + # Base configuration - always transform the main tag + # Transforms v1.32.4-rc1+k3s1 → v1.32.4-rc1-k3s1 + BASE_CONFIG="type=raw,value=${TAG//+/-}" + + if [[ "${TAG,,}" == *"rc"* ]]; then + echo "RC release detected: $TAG" + echo "tag_spec=$BASE_CONFIG" >> $GITHUB_OUTPUT + else + echo "Stable release detected: $TAG" + echo "tag_spec=$BASE_CONFIG + type=semver,pattern=v{{major}}.{{minor}}" >> $GITHUB_OUTPUT + fi + + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository_owner }}/k3s + flavor: latest=false + tags: ${{ steps.tag_config.outputs.tag_spec }} + + - name: "Download K3s build" + uses: actions/download-artifact@v4 + with: + pattern: k3s* + path: ./dist/artifacts + merge-multiple: true + + - name: Prepare build folder + run: | + mkdir -p ./build/out + cp ./dist/artifacts/data-* ./build/out + + - name: Build and push K3s runtime image + uses: docker/build-push-action@v6 + with: + context: . + file: ./package/Dockerfile + platforms: linux/amd64,linux/arm64,linux/arm/v7 + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + build-args: | + DRONE_TAG=${{ github.ref_name }} + diff --git a/package/Dockerfile b/package/Dockerfile index 0f12c353883..4dce79fe16d 100644 --- a/package/Dockerfile +++ b/package/Dockerfile @@ -1,8 +1,15 @@ FROM alpine:3.21 AS base RUN apk add -U ca-certificates zstd tzdata -COPY build/out/data-linux.tar.zst / -RUN mkdir -p /image/etc/ssl/certs /image/run /image/var/run /image/tmp /image/lib/modules /image/lib/firmware /image/var/lib/rancher/k3s/data/cni && \ - zstdcat -d /data-linux.tar.zst | tar -xa -C /image && \ +ARG TARGETARCH +COPY build/out/data-linux*.tar.zst / +RUN SOURCE_TAR_ZST="/data-linux-${TARGETARCH}.tar.zst" && \ + # If the arch-specific file doesn't exist, try the default one (used with Dapper or single-arch) + if [ ! -f "${SOURCE_TAR_ZST}" ]; then \ + SOURCE_TAR_ZST="/data-linux.tar.zst" ; \ + fi && \ + \ + mkdir -p /image/etc/ssl/certs /image/run /image/var/run /image/tmp /image/lib/modules /image/lib/firmware /image/var/lib/rancher/k3s/data/cni && \ + zstdcat -d "${SOURCE_TAR_ZST}" | tar -xa -C /image && \ for FILE in cni $(/image/bin/find /image/bin -lname cni -printf "%f\n"); do ln -s /bin/cni /image/var/lib/rancher/k3s/data/cni/$FILE; done && \ echo "root:x:0:0:root:/:/bin/sh" > /image/etc/passwd && \ echo "root:x:0:" > /image/etc/group && \ diff --git a/scripts/package-airgap b/scripts/package-airgap index ce27ae680e9..36c4084db96 100755 --- a/scripts/package-airgap +++ b/scripts/package-airgap @@ -9,9 +9,20 @@ if [ "${OS}" != "linux" ]; then exit fi +# Used by GHA to inject --platform=linux/(NON_x86_ARCH) on amd64 runners +OPT_ARCH=${1:-""} +if [ -n "${OPT_ARCH}" ]; then + ARCH=${OPT_ARCH} + if [ "${ARCH}" = "arm" ]; then + OPT_PLATFORM="--platform=linux/arm/v7" + else + OPT_PLATFORM="--platform=linux/${ARCH}" + fi +fi + airgap_image_file='scripts/airgap/image-list.txt' images=$(cat "${airgap_image_file}") -xargs -n1 docker pull <<< "${images}" +xargs -n1 docker pull ${OPT_PLATFORM} <<< "${images}" docker save ${images} -o dist/artifacts/k3s-airgap-images-${ARCH}.tar zstd --no-progress -T0 -16 -f --long=25 dist/artifacts/k3s-airgap-images-${ARCH}.tar -o dist/artifacts/k3s-airgap-images-${ARCH}.tar.zst pigz -v -c dist/artifacts/k3s-airgap-images-${ARCH}.tar > dist/artifacts/k3s-airgap-images-${ARCH}.tar.gz