From e42af70a36eada54ab4c52df6e425effcf1d3914 Mon Sep 17 00:00:00 2001 From: Ihor Solodrai Date: Fri, 30 Jan 2026 16:18:46 -0800 Subject: [PATCH] Container image for AI code reviews with semcode The ai-review.Dockerfile bakes in: - semcode binaries - semcode database with indexed bpf-next and bpf lore - mirror of the Linux source tree - latest git built from source Signed-off-by: Ihor Solodrai --- .github/workflows/build-ai-review-image.yml | 48 +++++++++++++++++++ ai-review.Dockerfile | 53 +++++++++++++++++++++ build-git.sh | 44 +++++++++++++++++ build-semcode.sh | 30 ++++++++++++ setup-mirror-repos.sh | 8 ++-- 5 files changed, 180 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/build-ai-review-image.yml create mode 100644 ai-review.Dockerfile create mode 100644 build-git.sh create mode 100755 build-semcode.sh diff --git a/.github/workflows/build-ai-review-image.yml b/.github/workflows/build-ai-review-image.yml new file mode 100644 index 0000000..7cc831b --- /dev/null +++ b/.github/workflows/build-ai-review-image.yml @@ -0,0 +1,48 @@ +name: Build AI review image + +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + TAG_SUFFIX: ${{ github.event_name == 'pull_request' && format('-pr-{0}', github.event.pull_request.number) || '' }} + PUBLISH: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }} + +jobs: + build: + runs-on: + - ${{ format('codebuild-bpf-ci-{0}-{1}', github.run_id, github.run_attempt) }} + - image:linux-5.0 + - instance-size:xlarge + permissions: + contents: read + packages: write + id-token: write + steps: + + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Setup Docker buildx + uses: docker/setup-buildx-action@v3 + + - name: Log into registry ${{ env.REGISTRY }} + if: ${{ env.PUBLISH }} + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: . + file: ai-review.Dockerfile + push: ${{ env.PUBLISH }} + tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:ai-review${{ env.TAG_SUFFIX }} diff --git a/ai-review.Dockerfile b/ai-review.Dockerfile new file mode 100644 index 0000000..8c4560d --- /dev/null +++ b/ai-review.Dockerfile @@ -0,0 +1,53 @@ +ARG DEBIAN_FRONTEND=noninteractive +ARG RUNNER_VERSION=2.331.0 + +### git builder +FROM debian:latest AS git-builder +ARG DEBIAN_FRONTEND RUNNER_VERSION +RUN apt-get update -y && apt-get install -y --no-install-recommends \ + ca-certificates curl sudo +COPY build-git.sh /tmp/build-git.sh +RUN bash /tmp/build-git.sh + + +### semcode builder +FROM debian:latest AS semcode-builder +ARG DEBIAN_FRONTEND RUNNER_VERSION +RUN apt-get update -y && apt-get install -y --no-install-recommends \ + ca-certificates curl git sudo wget +COPY build-semcode.sh /tmp/build-semcode.sh +RUN bash /tmp/build-semcode.sh + + +### AI runtime +FROM debian:latest as runtime +ARG DEBIAN_FRONTEND RUNNER_VERSION + +RUN apt-get update -y && apt-get install -y --no-install-recommends \ + ca-certificates curl libcurl3-gnutls sudo wget unzip + +# Install pre-requisites for GitHub Actions Runner client app +# https://github.com/actions/runner/blob/main/docs/start/envlinux.md +RUN curl -Lf https://raw.githubusercontent.com/actions/runner/v${RUNNER_VERSION}/src/Misc/layoutbin/installdependencies.sh \ + -o /tmp/install-gha-runner-deps.sh +RUN bash /tmp/install-gha-runner-deps.sh + +COPY --from=git-builder /opt/git-staging/usr/local /usr/local + +ENV MIRRORS_PATH=/ci/mirrors +COPY setup-mirror-repos.sh /tmp/setup-mirror-repos.sh +RUN bash /tmp/setup-mirror-repos.sh +RUN mkdir -p /libbpfci/mirrors && ln -s ${MIRRORS_PATH}/linux /libbpfci/mirrors/linux + +COPY --from=semcode-builder /opt/semcode /usr/local/bin/semcode +COPY --from=semcode-builder /opt/semcode-index /usr/local/bin/semcode-index +COPY --from=semcode-builder /opt/semcode-mcp /usr/local/bin/semcode-mcp +COPY --from=semcode-builder /opt/semcode-lsp /usr/local/bin/semcode-lsp + +RUN cd ${MIRRORS_PATH}/linux && \ + git remote add torvalds https://github.com/torvalds/linux.git && \ + git fetch torvalds && \ + git checkout origin/bpf-next +RUN cd ${MIRRORS_PATH}/linux && \ + semcode-index -d /ci/.semcode.db --git $(git describe --tags --abbrev=0)..HEAD +RUN semcode-index -d /ci/.semcode.db --lore bpf diff --git a/build-git.sh b/build-git.sh new file mode 100644 index 0000000..030a0fa --- /dev/null +++ b/build-git.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +set -xeuo pipefail + +# Build git from source using official kernel.org tarballs +# Usage: ./build-git.sh [version] +# If version is not specified, fetches the latest release + +GIT_VERSION=${1:-} +GIT_MIRROR=${GIT_MIRROR:-https://mirrors.edge.kernel.org/pub/software/scm/git} + +# Install build dependencies +sudo apt-get update -y +sudo apt-get install -y --no-install-recommends \ + build-essential \ + ca-certificates \ + curl \ + gettext \ + libcurl4-gnutls-dev \ + libexpat1-dev \ + libssl-dev \ + zlib1g-dev + +# Determine version to install +if [ -z "${GIT_VERSION}" ]; then + echo "Fetching latest git version..." + GIT_VERSION=$(curl -fsSL "${GIT_MIRROR}/" | \ + grep -oP 'git-\K[0-9]+\.[0-9]+\.[0-9]+(?=\.tar\.gz)' | \ + sort -V | tail -1) +fi + +echo "Building git version: ${GIT_VERSION}" + +WORKDIR=$(mktemp -d) +cd "${WORKDIR}" + +curl -fsSL "${GIT_MIRROR}/git-${GIT_VERSION}.tar.gz" | tar xz +cd "git-${GIT_VERSION}" + +make prefix=/usr/local -j$(nproc) all +sudo make prefix=/usr/local DESTDIR=/opt/git-staging install + +cd / +rm -rf "${WORKDIR}" diff --git a/build-semcode.sh b/build-semcode.sh new file mode 100755 index 0000000..2abb238 --- /dev/null +++ b/build-semcode.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +set -xeuo pipefail + +SEMCODE_ORIGIN=${SEMCODE_ORIGIN:-https://github.com/facebookexperimental/semcode.git} +SEMCODE_REVISION=${SEMCODE_REVISION:-main} +SEMCODE_SRC=${SEMCODE_SRC:-/tmp/semcode} + +sudo apt-get install -y build-essential libclang-dev protobuf-compiler libprotobuf-dev libssl-dev pkg-config + +# Install Rust +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + +if [[ ! -d $SEMCODE_SRC ]]; then + cd /tmp + git clone ${SEMCODE_ORIGIN} semcode + cd semcode + git checkout ${SEMCODE_REVISION} -b local +else + cd $SEMCODE_SRC +fi + +. $HOME/.cargo/env +cargo build --release + +cd target/release +cp semcode /opt/semcode +cp semcode-index /opt/semcode-index +cp semcode-mcp /opt/semcode-mcp +cp semcode-lsp /opt/semcode-lsp diff --git a/setup-mirror-repos.sh b/setup-mirror-repos.sh index bdc9e45..6e9d925 100755 --- a/setup-mirror-repos.sh +++ b/setup-mirror-repos.sh @@ -2,6 +2,8 @@ set -euo pipefail -mkdir -p /libbpfci/mirrors -git clone https://github.com/kernel-patches/bpf.git /libbpfci/mirrors/linux -chmod -R a+rX /libbpfci/mirrors +MIRRORS_PATH=${MIRRORS_PATH:-/libbpfci/mirrors} + +mkdir -p "$MIRRORS_PATH" +git clone https://github.com/kernel-patches/bpf.git "$MIRRORS_PATH/linux" +chmod -R a+rX "$MIRRORS_PATH"