name: Release # Triggered by `git push origin vX.Y.Z`. Builds Go binaries (amd64+arm64), # x86_64 ISO + disk image, ARM64 disk image, computes SHA256SUMS over all # artifacts, and posts a Gitea release with everything attached via the # Gitea API. # # Notes for future-you: # - upload-artifact / download-artifact are pinned to @v3 because Gitea's # act_runner v1.0.x doesn't fully implement v4 yet. # - The release step uses curl against Gitea's own /api/v1/repos/.../releases # instead of a third-party action (softprops/action-gh-release et al); # act_runner doesn't reliably proxy GitHub.com-targeted actions. # - The arm64 disk-image build runs on the Odroid self-hosted runner via # the `arm64-linux` label. Docs in docs/ci-runners.md. on: push: tags: - 'v*' jobs: test: name: Test runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.22' - name: Test cloud-init run: cd cloud-init && go test ./... -count=1 - name: Test update agent run: cd update && go test ./... -count=1 build-binaries: name: Build Binaries (${{ matrix.suffix }}) runs-on: ubuntu-latest needs: test strategy: matrix: include: - goos: linux goarch: amd64 suffix: linux-amd64 - goos: linux goarch: arm64 suffix: linux-arm64 steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.22' - name: Get version id: version run: echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT - name: Build cloud-init run: | CGO_ENABLED=0 GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} \ go build -ldflags="-s -w -X main.version=${{ steps.version.outputs.version }}" \ -o kubesolo-cloudinit-${{ matrix.suffix }} ./cmd/ working-directory: cloud-init - name: Build update agent run: | CGO_ENABLED=0 GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} \ go build -ldflags="-s -w -X main.version=${{ steps.version.outputs.version }}" \ -o kubesolo-update-${{ matrix.suffix }} . working-directory: update - name: Upload binaries uses: actions/upload-artifact@v3 with: name: binaries-${{ matrix.suffix }} path: | cloud-init/kubesolo-cloudinit-${{ matrix.suffix }} update/kubesolo-update-${{ matrix.suffix }} build-iso-amd64: name: Build x86_64 ISO + disk image runs-on: ubuntu-latest needs: build-binaries steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.22' - name: Install build deps run: | sudo apt-get update sudo apt-get install -y --no-install-recommends \ cpio gzip genisoimage isolinux syslinux syslinux-common \ syslinux-utils xorriso xz-utils wget squashfs-tools \ dosfstools e2fsprogs fdisk parted libarchive-tools \ grub-common grub-efi-amd64-bin grub-pc-bin kpartx \ busybox-static iptables nftables - name: Build kernel + ISO + disk-image run: | make kernel make build-cloudinit build-update-agent make rootfs initramfs make iso make disk-image - name: Compress disk image # The raw .img is 4 GB sparse; xz takes it to ~50-300 MB depending # on dictionary level. Use -6 (default) for memory safety on the # GitHub-Actions-style runner. run: | xz -k -T0 --memlimit-compress=1500MiB -6 output/*.img ls -lh output/ - name: Upload x86_64 artifacts uses: actions/upload-artifact@v3 with: name: image-amd64 path: | output/*.iso output/*.img.xz build-disk-arm64: name: Build ARM64 disk image runs-on: arm64-linux needs: test steps: - uses: actions/checkout@v4 - name: Show host info run: | uname -a nproc free -h df -h / - name: Build kernel + rootfs + disk-image # Runner runs as root via systemd; explicit sudo is harmless but # documented as such in docs/ci-runners.md. run: | make kernel-arm64 make build-cross make rootfs-arm64 make disk-image-arm64 - name: Compress disk image run: | xz -k -T0 --memlimit-compress=1500MiB -6 output/*.arm64.img ls -lh output/ - name: Upload ARM64 artifacts uses: actions/upload-artifact@v3 with: name: image-arm64 path: output/*.arm64.img.xz release: name: Publish Gitea Release runs-on: ubuntu-latest needs: [build-binaries, build-iso-amd64, build-disk-arm64] steps: - uses: actions/checkout@v4 - name: Get version id: version # `cat VERSION` would be stale on tag pushes (VERSION already bumped # for the tag, but using ref_name is unambiguous). run: echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT - name: Download all artifacts uses: actions/download-artifact@v3 with: path: artifacts - name: Flatten artifacts + compute checksums run: | mkdir -p release # Each upload-artifact wrote into artifacts//... find artifacts -type f \( \ -name "*.iso" -o \ -name "*.img.xz" -o \ -name "kubesolo-*" \ \) -exec cp {} release/ \; (cd release && sha256sum * | sort > SHA256SUMS) ls -lh release/ cat release/SHA256SUMS - name: Install release tooling run: sudo apt-get update && sudo apt-get install -y jq curl - name: Render release body id: body run: | VERSION="${{ steps.version.outputs.version }}" # Strip the leading 'v' for cosmetic display in the body. DISPLAY="${VERSION#v}" cat > release-body.md < Creating release for $TAG against $REPO_API" CREATE_RESP=$(curl -fsSL -X POST \ -H "Authorization: token $TOKEN" \ -H "Content-Type: application/json" \ -d "$PAYLOAD" \ "$REPO_API/releases") RELEASE_ID=$(echo "$CREATE_RESP" | jq -r '.id') if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "null" ]; then echo "ERROR: Could not extract release id from response:" echo "$CREATE_RESP" | jq . || echo "$CREATE_RESP" exit 1 fi echo "==> Release id: $RELEASE_ID" # 2. Upload each asset. asset?name= names the attachment; we use # the basename so users see the same filename the build produced. for f in release/*; do [ -f "$f" ] || continue name=$(basename "$f") echo "==> Uploading $name ($(du -h "$f" | cut -f1))" curl -fsSL -X POST \ -H "Authorization: token $TOKEN" \ -F "attachment=@$f" \ "$REPO_API/releases/$RELEASE_ID/assets?name=$name" >/dev/null done echo "==> Release published: $REPO_API/../releases/tag/$TAG"