Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Build
name: Build Lima & QEMU Bundle

# Runs every Tuesday at 9 am UTC
on:
Expand All @@ -9,7 +9,7 @@ on:
branches:
- main
paths:
- .github/workflows/release.yaml
- .github/workflows/build-lima-and-qemu.yaml
- src/lima/**
- deps/qemu.conf
- bin/lima-and-qemu.py
Expand Down Expand Up @@ -68,13 +68,20 @@ jobs:

- name: Make and release deps
run: |
# (cd src/lima && git clean -f -d && git am ../patches/lima/*.patch)
cd src/lima
git clean -f -d
git am ../patches/lima/*.patch

sudo make clean native install PREFIX=/opt/homebrew || exit 1
echo "Installed limactl version: $(limactl --version)"

cd ../../
python3 bin/lima-and-qemu.py
if [ $? -ne 0 ]; then
echo "Failed to create lima-and-qemu archive"
exit 1
fi

mv src/lima/lima-and-qemu.tar.gz src/lima/lima-and-qemu.macos-aarch64.tar.gz
shell: zsh {0}

Expand Down Expand Up @@ -150,13 +157,20 @@ jobs:

- name: Make and release deps
run: |
# (cd src/lima && git clean -f -d && git am ../patches/lima/*.patch)
cd src/lima
sudo make clean native install PREFIX=/opt/homebrew || exit 1
git clean -f -d
git am ../patches/lima/*.patch

sudo make clean native install PREFIX=/usr/local || exit 1
echo "Installed limactl version: $(limactl --version)"

cd ../../
python3 bin/lima-and-qemu.py
if [ $? -ne 0 ]; then
echo "Failed to create lima-and-qemu archive"
exit 1
fi

mv src/lima/lima-and-qemu.tar.gz src/lima/lima-and-qemu.macos-x86_64.tar.gz
shell: zsh {0}

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ Note that the vm instance is NOT expected to exist before running the tests, ple

### Maintaining QEMU Version

The version of QEMU that is shipped with finch is the same version that is installed on the GitHub action runners as part of the `release.yaml` workflow. The QEMU version that is installed (and therefore shipped) is configurable in the `deps/qemu.conf` file. We use homebrew to install QEMU on the runners and since homebrew updates its formula files in place, in order to pin a version of QEMU, we need to find a specific commit that corresponds to that version. To do that -
The version of QEMU that is shipped with finch is the same version that is installed on the GitHub action runners as part of the `build-lima-and-qemu.yaml` workflow. The QEMU version that is installed (and therefore shipped) is configurable in the `deps/qemu.conf` file. We use homebrew to install QEMU on the runners and since homebrew updates its formula files in place, in order to pin a version of QEMU, we need to find a specific commit that corresponds to that version. To do that -

- Go to https://github.com/Homebrew/homebrew-core/commits/main/Formula/q/qemu.rb
- Find the commit for the specific version. For example - `6dd3cf36c974c9a69df5d2b0e5d3f4de3df30e77` for version `10.1.0`.
- Replace `QEMU_VERSION` and `QEMU_FORMULA_GH_COMMIT` with the appropriate values in the `deps/qemu.conf` file.
- Trigger the `release.yaml` or `Build` workflow.
- Trigger the `build-lima-and-qemu.yaml` or `Build` workflow.

**NOTE:** This version of QEMU is **not** the same as the version of QEMU that is installed inside the Finch VM. This is the QEMU version that will be used by Finch to launch the Finch VM when `vmType=qemu` is specified in `finch.yaml` configuration file.
58 changes: 54 additions & 4 deletions bin/lima-and-qemu.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import shutil
import re
import tarfile
import gzip
import json
from enum import Enum
from collections import defaultdict
Expand Down Expand Up @@ -33,6 +34,9 @@ def main():

qemu_version = get_installed_qemu_version()
print("using qemu version: ", qemu_version)

lima_version = get_installed_lima_version()
print("using lima version: ", lima_version)

print("recording initial deps...")
deps = record_initial_deps(arch, install_dir, qemu_version)
Expand Down Expand Up @@ -64,15 +68,21 @@ def main():
extract_and_export_package_versions(deps, arch, install_dir)

print("Packaging files and socket_vmnet...")
package_files_and_socket_vmnet(deps, install_dir, dist_path)
archive_path = package_files_and_socket_vmnet(deps, install_dir, dist_path)

print("adding lima version info to built archive...")
add_lima_version_to_archive(archive_path, lima_version)

print("compressing archive...")
compress_archive(archive_path)

print("Cleaning up...")
cleanup()

print("Done")

def get_templates_from_args():
default_templates = ["alpine", "default"]
default_templates = ["fedora-42", "default"]
return sys.argv[1:] if len(sys.argv) > 1 else default_templates

def get_system_arch():
Expand All @@ -84,6 +94,16 @@ def get_system_arch():
def get_installation_dir(arch: Literal[Arch.X86_64, Arch.AARCH64]):
return "/usr/local" if arch == Arch.X86_64 else "/opt/homebrew"

def get_installed_lima_version():
try:
res = subprocess.check_output("limactl --version", shell=True, text=True)
lima_version = res.replace("limactl version", "").strip()
if not lima_version:
raise RuntimeError("failed to get installed lima version")
return lima_version
except Exception as ex:
raise RuntimeError("failed to get installed lima version") from ex

def get_installed_qemu_version():
try:
res = subprocess.check_output("brew list --versions qemu", shell=True, text=True)
Expand Down Expand Up @@ -223,6 +243,35 @@ def resign(resign_files: Set[str]):
except Exception as ex:
raise RuntimeError(f"failed to resign {file_path}") from ex

def compress_archive(archive_path: str):
if not os.path.exists(archive_path):
raise RuntimeError("{archive_path} does not exist")

try:
lima_repo_root = os.path.join(os.getcwd(), 'src', 'lima')
compressed_tarball_path = f"{lima_repo_root}/lima-and-qemu.tar.gz"
if os.path.exists(compressed_tarball_path):
os.unlink(compressed_tarball_path)
with open(archive_path, "rb") as f_in, gzip.open(compressed_tarball_path, "wb") as f_out:
shutil.copyfileobj(f_in, f_out)
except Exception as ex:
raise RuntimeError("failed to compress archive {archive_path}") from ex

def add_lima_version_to_archive(archive_path: str, lima_version: str):
try:
if not os.path.exists(archive_path):
raise RuntimeError(f"archive {archive_path} does not exist")

with open("LIMA_VERSION", "w") as f:
f.write(lima_version)
print(f"Created LIMA_VERSION file with content: {lima_version}")

with tarfile.open(archive_path, "a" ) as tar:
tar.add("LIMA_VERSION", arcname="LIMA_VERSION")
print(f"Added LIMA_VERSION file to archive {archive_path}")
except Exception as ex:
raise RuntimeError("failed to add LIMA_VERSION to archive") from ex

def package_files_and_socket_vmnet(deps: Dict[str, str], install_dir: str, dist_path: str):
tar_files = [path.removeprefix(f"{install_dir}/") for path in deps.keys()]

Expand All @@ -249,13 +298,14 @@ def package_files_and_socket_vmnet(deps: Dict[str, str], install_dir: str, dist_

try:
lima_repo_root = os.path.join(os.getcwd(), 'src', 'lima')
tarball_path = f"{lima_repo_root}/lima-and-qemu.tar.gz"
tarball_path = f"{lima_repo_root}/lima-and-qemu.tar"
if os.path.exists(tarball_path):
os.unlink(tarball_path)
with tarfile.open(tarball_path, "w:gz") as tar:
with tarfile.open(tarball_path, "w") as tar:
for file in tar_files:
print(f"adding {dist_path}/{file} to tarball")
tar.add(f"{dist_path}/{file}", arcname=file)
return tarball_path
except Exception as ex:
raise RuntimeError("failed to package files") from ex

Expand Down
12 changes: 10 additions & 2 deletions bin/update-lima-bundles.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,23 @@ aarch64_deps=$(find_latest_object_match_from_s3 "${AARCH64_FILENAME_PATTERN}" "$
# Need to pull the shasum of the artifact to store for later verification.
aarch64_deps_shasum_url="${DEPENDENCY_CLOUDFRONT_URL}/${aarch64_deps}.sha512sum"
aarch64_deps_shasum=$(curl -L --fail "${aarch64_deps_shasum_url}")

pull_artifact_and_verify_shasum "${DEPENDENCY_CLOUDFRONT_URL}/${aarch64_deps}" "${aarch64_deps_shasum}"

amd64_deps=$(find_latest_object_match_from_s3 "${AMD64_FILENAME_PATTERN}" "${dependency_bucket}/${X86_64}")
[[ -z "$amd64_deps" ]] && { echo "Error: x86_64 dependency not found"; exit 1; }

amd64_deps_shasum_url="${DEPENDENCY_CLOUDFRONT_URL}/${amd64_deps}.sha512sum"
amd64_deps_shasum=$(curl -L --fail "${amd64_deps_shasum_url}")

pull_artifact_and_verify_shasum "${DEPENDENCY_CLOUDFRONT_URL}/${amd64_deps}" "${amd64_deps_shasum}"

# make sure the lima version for both matches
lima_version_aarch64=$(get_lima_version_from_deps "${DEPENDENCY_CLOUDFRONT_URL}/${aarch64_deps}")
lima_version_amd64=$(get_lima_version_from_deps "${DEPENDENCY_CLOUDFRONT_URL}/${amd64_deps}")
if [[ "$lima_version_aarch64" != "$lima_version_amd64" ]]; then
echo "Error: lima versions do not match b/w two dependency archives: ${lima_version_aarch64} vs ${lima_version_amd64}"
exit 1
fi

# Update bundles file with latest artifacts and digests.
BUNDLES_FILE="${PROJECT_ROOT}/deps/lima-bundles.conf"
truncate -s 0 "${BUNDLES_FILE}"
Expand All @@ -60,4 +66,6 @@ truncate -s 0 "${BUNDLES_FILE}"
echo "X86_64_ARTIFACT_PATHING=${X86_64}"
echo "X86_64_ARTIFACT=$(basename "${amd64_deps}")"
echo "X86_64_512_DIGEST=${amd64_deps_shasum}"
echo ""
echo "LIMA_VERSION=${lima_version_aarch64}"
} >> "${BUNDLES_FILE}"
14 changes: 14 additions & 0 deletions bin/utility.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,17 @@ pull_artifact_and_verify_shasum() {
shasum --algorithm 512 "${artifact}" | cut -d ' ' -f 1 | grep -xq "^${expected_shasum}$" || \
(echo "error: shasum verification failed for \"${artifact}\" dependency" && rm -f "${artifact}" && exit 1)
}

# pulls articact, extracts and reads LIMA_VERSION file from the artifact
#
# @param artifact_url - URL to artifact
# @return lima version number
get_lima_version_from_deps() {
local artifact_url="$1"
artifact=$(basename "$artifact_url")
curl -L --fail "${artifact_url}" > "${artifact}"
tar -xzf "${artifact}" ./LIMA_VERSION
lima_version="$(cat LIMA_VERSION | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')"
rm -f "${artifact}" ./LIMA_VERSION
echo "${lima_version}"
}
8 changes: 4 additions & 4 deletions deps-verification-arm64.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
/opt/homebrew/Cellar/libpng/1.6.50/lib/libpng16.dylib → libpng16.16.dylib
/opt/homebrew/Cellar/libslirp/4.9.1/lib/libslirp.0.dylib [164K]
/opt/homebrew/Cellar/libslirp/4.9.1/lib/libslirp.dylib → libslirp.0.dylib
/opt/homebrew/Cellar/libssh/0.11.3/lib/libssh.4.10.3.dylib [469K]
/opt/homebrew/Cellar/libssh/0.11.3/lib/libssh.4.dylib → libssh.4.10.3.dylib
/opt/homebrew/Cellar/libssh/0.11.3/lib/libssh.dylib → libssh.4.dylib
/opt/homebrew/Cellar/libssh/0.12.0/lib/libssh.4.11.0.dylib [469K]
/opt/homebrew/Cellar/libssh/0.12.0/lib/libssh.4.dylib → libssh.4.11.0.dylib
/opt/homebrew/Cellar/libssh/0.12.0/lib/libssh.dylib → libssh.4.dylib
/opt/homebrew/Cellar/libtasn1/4.20.0/lib/libtasn1.6.dylib [106K]
/opt/homebrew/Cellar/libtasn1/4.20.0/lib/libtasn1.dylib → libtasn1.6.dylib
/opt/homebrew/Cellar/libunistring/1.3/lib/libunistring.5.dylib [1.9M]
Expand Down Expand Up @@ -109,6 +109,6 @@
/opt/homebrew/opt/zstd → ../Cellar/zstd/1.5.7
/opt/homebrew/share/lima/lima-guestagent.Linux-aarch64.gz [12M]
/opt/homebrew/share/lima/templates/_default/mounts.yaml [104B]
/opt/homebrew/share/lima/templates/_images/alpine.yaml [592B]
/opt/homebrew/share/lima/templates/_images/fedora-42.yaml [592B]
/opt/homebrew/share/lima/templates/_images/ubuntu.yaml [2.4K]
/opt/homebrew/share/qemu → ../Cellar/qemu/10.1.0/share/qemu
8 changes: 4 additions & 4 deletions deps-verification-x86.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@
/usr/local/Cellar/libpng/1.6.50/lib/libpng16.dylib → libpng16.16.dylib
/usr/local/Cellar/libslirp/4.9.1/lib/libslirp.0.dylib [146K]
/usr/local/Cellar/libslirp/4.9.1/lib/libslirp.dylib → libslirp.0.dylib
/usr/local/Cellar/libssh/0.11.3/lib/libssh.4.10.3.dylib [448K]
/usr/local/Cellar/libssh/0.11.3/lib/libssh.4.dylib → libssh.4.10.3.dylib
/usr/local/Cellar/libssh/0.11.3/lib/libssh.dylib → libssh.4.dylib
/usr/local/Cellar/libssh/0.12.0/lib/libssh.4.11.0.dylib [483K]
/usr/local/Cellar/libssh/0.12.0/lib/libssh.4.dylib → libssh.4.11.0.dylib
/usr/local/Cellar/libssh/0.12.0/lib/libssh.dylib → libssh.4.dylib
/usr/local/Cellar/libtasn1/4.20.0/lib/libtasn1.6.dylib [103K]
/usr/local/Cellar/libtasn1/4.20.0/lib/libtasn1.dylib → libtasn1.6.dylib
/usr/local/Cellar/libunistring/1.3/lib/libunistring.5.dylib [1.9M]
Expand Down Expand Up @@ -111,6 +111,6 @@
/usr/local/opt/zstd → ../Cellar/zstd/1.5.7
/usr/local/share/lima/lima-guestagent.Linux-x86_64.gz [13M]
/usr/local/share/lima/templates/_default/mounts.yaml [104B]
/usr/local/share/lima/templates/_images/alpine.yaml [592B]
/usr/local/share/lima/templates/_images/fedora-42.yaml [592B]
/usr/local/share/lima/templates/_images/ubuntu.yaml [2.4K]
/usr/local/share/qemu → ../Cellar/qemu/10.1.0/share/qemu
2 changes: 2 additions & 0 deletions deps/lima-bundles.conf
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ AARCH64_512_DIGEST=b75d22b7f4d7d3443daf5ac4ebfa3b51f73c37854f4109150800ce11a3b99
X86_64_ARTIFACT_PATHING=x86-64
X86_64_ARTIFACT=lima-and-qemu.macos-x86_64.1770936353.tar.gz
X86_64_512_DIGEST=f26f68dc3d6dc7f8bc5577d63d611b1446ea8762d13b0962d3ab37bdf6839bc2a3b525c88628f2c2869ecffd636be10980aa6cbeb2bf1b367ee505fd82a75bd8

LIMA_VERSION=2.0.3
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
From 21375c3df1144005159aff95f73b04cd0b455478 Mon Sep 17 00:00:00 2001
From: Swapnanil Gupta <swpnlg@amazon.com>
Date: Thu, 12 Feb 2026 18:20:26 +0000
Subject: [PATCH] fix: make qemu convertToRaw handle symlinked dests

Signed-off-by: Swapnanil Gupta <swpnlg@amazon.com>
---
pkg/qemuimgutil/qemuimgutil.go | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/pkg/qemuimgutil/qemuimgutil.go b/pkg/qemuimgutil/qemuimgutil.go
index 14ad4d47..9a5b085f 100644
--- a/pkg/qemuimgutil/qemuimgutil.go
+++ b/pkg/qemuimgutil/qemuimgutil.go
@@ -120,6 +120,14 @@ func convertToRaw(ctx context.Context, source, dest string) error {
return nil
}

+ realDest, _ := os.Readlink(dest)
+ if realDest != "" && realDest != dest {
+ dest = realDest
+ }
+
tempFile := dest + ".lima-qemu-convert.tmp"
defer os.Remove(tempFile)

--
2.47.3

This file was deleted.

Loading