Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
118 changes: 0 additions & 118 deletions .github/workflows/fc-kernels.yml

This file was deleted.

119 changes: 119 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
name: Build & Release

on:
workflow_dispatch:
Comment thread
ValentaTomas marked this conversation as resolved.
pull_request:

permissions:
Comment thread
ValentaTomas marked this conversation as resolved.
contents: write
id-token: write

jobs:
matrix:
runs-on: ubuntu-24.04
outputs:
build_matrix: ${{ steps.gen.outputs.matrix }}
steps:
- uses: actions/checkout@v4
- id: gen
run: |
python3 - >> "$GITHUB_OUTPUT" <<'PY'
import json
versions = []
for line in open("kernel_versions.txt").read().splitlines():
v = line.split("#", 1)[0].strip()
if v:
versions.append(v)
include = []
for v in versions:
include.append({"version": v, "arch": "amd64", "target_arch": "x86_64", "runner": "ubuntu-24.04"})
include.append({"version": v, "arch": "arm64", "target_arch": "arm64", "runner": "ubuntu-24.04-arm"})
print(f"matrix={json.dumps({'include': include})}")
PY

build:
needs: matrix
name: Build ${{ matrix.version }} (${{ matrix.arch }})
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.matrix.outputs.build_matrix) }}
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v4

- name: Build kernel
run: sudo ./build.sh "${{ matrix.version }}" "${{ matrix.target_arch }}"
Comment thread
ValentaTomas marked this conversation as resolved.
Outdated

- uses: actions/upload-artifact@v4
with:
name: kernel-${{ matrix.version }}-${{ matrix.arch }}
path: ./builds
retention-days: 7

publish:
needs: build
if: github.event_name == 'workflow_dispatch'
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: actions/download-artifact@v4
with:
path: ./builds
merge-multiple: true

- name: Prepare release assets
run: |
set -euo pipefail
mkdir -p release-assets
for dir in ./builds/vmlinux-*/; do
name=$(basename "$dir")
[ -f "$dir/amd64/vmlinux.bin" ] && cp "$dir/amd64/vmlinux.bin" "release-assets/${name}-amd64.bin"
[ -f "$dir/arm64/vmlinux.bin" ] && cp "$dir/arm64/vmlinux.bin" "release-assets/${name}-arm64.bin"
# Legacy non-arch-suffixed asset (= amd64) for backwards compat.
[ -f "$dir/vmlinux.bin" ] && cp "$dir/vmlinux.bin" "release-assets/${name}.bin"
done
ls -la release-assets/

- name: Pick calver tag
id: tag
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
base="$(date -u +%Y.%m.%d)"
tag="$base"
n=0
while gh release view "$tag" >/dev/null 2>&1; do
n=$((n + 1))
tag="${base}.${n}"
done
Comment thread
ValentaTomas marked this conversation as resolved.
echo "tag=$tag" >> "$GITHUB_OUTPUT"
Comment thread
cursor[bot] marked this conversation as resolved.

- name: Create release
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag "${{ steps.tag.outputs.tag }}"
git push origin "${{ steps.tag.outputs.tag }}"
gh release create "${{ steps.tag.outputs.tag }}" \
--title "Kernels ${{ steps.tag.outputs.tag }}" \
--notes "Built from commit ${{ github.sha }} on ${{ github.ref_name }}" \
./release-assets/*

- uses: google-github-actions/auth@v2
with:
workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }}
service_account: ${{ secrets.GCP_SERVICE_ACCOUNT_EMAIL }}

- uses: google-github-actions/upload-cloud-storage@v2
with:
path: ./builds
destination: ${{ vars.GCP_BUCKET_NAME }}/kernels
gzip: false
parent: false
53 changes: 35 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,57 @@

## Overview

This project automates the building of custom Linux kernels for Firecracker microVMs, using the same kernel sources as official Firecracker repo and custom configuration files. It supports building specific kernel versions and uploading the resulting binaries to a Google Cloud Storage (GCS) bucket.
This project builds custom Linux kernels for Firecracker microVMs from the same kernel sources as the official Firecracker repo, using the configuration files (and optional patches) that live in this repo.

## Prerequisites

- Linux environment (for building kernels)

## Building Kernels
## Building locally

1. **Configure kernel versions:**
- Edit `kernel_versions.txt` to specify which kernel versions to build (one per line, e.g., `6.1.102`).
- Place the corresponding config file in `configs/` (e.g., `configs/6.1.102.config`).
- Edit `kernel_versions.txt` to specify which kernel versions to build (one per line, e.g. `6.1.158`).
- Place the corresponding config(s) in `configs/x86_64/<version>.config` and `configs/arm64/<version>.config`.
- (Optional) Drop `*.patch` files into `patches/<version>/` to apply on top of the upstream tree before build.

2. **Build:**
```sh
make build
# or directly
./build.sh
make build # builds all versions in kernel_versions.txt for x86_64
make build-arm64 # same, for arm64
./build.sh 6.1.158 # build a single version (x86_64)
./build.sh 6.1.158 arm64
```
The built kernels will be placed in `builds/vmlinux-<version>/<arch>/vmlinux.bin` where `<arch>` is `amd64` or `arm64` (Go/OCI convention). For x86_64 backward compatibility, a legacy copy is also placed at `builds/vmlinux-<version>/vmlinux.bin`.

## Development Workflow
- On every push, GitHub Actions will automatically build the kernels and save it as an artifact.
Output: `builds/vmlinux-<version>/<arch>/vmlinux.bin` where `<arch>` is `amd64` or `arm64` (Go/OCI convention). For x86_64 a legacy copy is also placed at `builds/vmlinux-<version>/vmlinux.bin`.

## CI / Releasing

The **Build & Release** workflow runs in two modes:

- **On every pull request**: builds every (kernel version × arch) combination from `kernel_versions.txt` in parallel (one runner per pair) and uploads the binaries as workflow artifacts (downloadable from the PR's checks tab) so reviewers can inspect them. No release or GCS upload happens.
- **Manually (workflow_dispatch)**: pick the branch in the GitHub UI and run. It does the same build as a PR and additionally creates a GitHub release tagged `YYYY.MM.DD` (with a `.N` suffix for additional runs the same day) containing every binary, and uploads them to GCS.

Release asset naming for that commit:

```
vmlinux-<version>-amd64.bin
vmlinux-<version>-arm64.bin
vmlinux-<version>.bin # legacy (= amd64) for backwards compat
```

4. The same binaries are uploaded to GCS at `gs://$GCP_BUCKET_NAME/kernels/vmlinux-<version>/<arch>/vmlinux.bin`.

## New kernel in E2B's infra
_Note: these steps should give you a new kernel on your self-hosted E2B using https://github.com/e2b-dev/infra_

- Run the release workflow on the branch with the new config/patch.
- Update `DefaultKernelVersion` in [packages/api/internal/cfg/model.go](https://github.com/e2b-dev/infra/blob/main/packages/api/internal/cfg/model.go) if you changed the kernel version.
- Build and deploy `api`.

## Architecture naming

Output directories use Go's `runtime.GOARCH` convention (`amd64`, `arm64`) so they match the infra orchestrator's `TargetArch()` path resolution. The build-time variable `TARGET_ARCH` (`x86_64`, `arm64`) is only used internally for config paths and cross-compilation flags.

## New Kernel in E2B's infra
_Note: these steps should give you new kernel on your self-hosted E2B using https://github.com/e2b-dev/infra_

- Copy the kernel build in your project's object storage under `e2b-*-fc-kernels`
- In [packages/api/internal/cfg/model.go](https://github.com/e2b-dev/infra/blob/main/packages/api/internal/cfg/model.go) update `DefaultKernelVersion`
- Build and deploy `api`

## License

This project is licensed under the Apache License 2.0. See [LICENSE](LICENSE) for details.
This project is licensed under the Apache License 2.0. See [LICENSE](LICENSE) for details.
Loading
Loading