diff --git a/.github/scripts/fork-changed-packages.py b/.github/scripts/fork-changed-packages.py new file mode 100644 index 000000000000..b7cdcf082705 --- /dev/null +++ b/.github/scripts/fork-changed-packages.py @@ -0,0 +1,32 @@ +"""Map changed file paths to their cargo package names. + +Reads `cargo metadata --no-deps --format-version 1` on stdin and file paths, +one per line, on argv. A file belongs to the package whose manifest directory +is the longest prefix of its path, so a nested crate wins over its parent and +the directory name never has to equal the package name. +""" + +import json +import os +import sys + +meta = json.load(sys.stdin) +root = os.getcwd() +dirs = [] +for package in meta["packages"]: + manifest = os.path.relpath(package["manifest_path"], root) + dirs.append((os.path.dirname(manifest), package["name"])) +dirs.sort(key=lambda entry: len(entry[0]), reverse=True) + +seen = [] +for argument in sys.argv[1:]: + path = os.path.normpath(argument) + prefix = "codex-rs" + os.sep + if path.startswith(prefix): + path = path[len(prefix):] + for directory, name in dirs: + if path == directory or path.startswith(directory + os.sep): + if name not in seen: + seen.append(name) + break +print("\n".join(seen)) diff --git a/.github/workflows/fork-ci.yml b/.github/workflows/fork-ci.yml new file mode 100644 index 000000000000..693d41cfcf35 --- /dev/null +++ b/.github/workflows/fork-ci.yml @@ -0,0 +1,111 @@ +# Fork-only CI. The upstream blocking-ci, CLA and v8-canary workflows are +# disabled on this fork, so this is the check that runs on fork pull requests. +# New file with a fork-unique name; no upstream workflow is edited. +name: fork-ci + +on: + pull_request: + branches: [fork/main] + workflow_dispatch: + +permissions: + contents: read + +jobs: + check: + name: fmt, clippy, test + runs-on: ubuntu-24.04 + # The workspace Cargo.toml is codex-rs/Cargo.toml; the repo root has none. + defaults: + run: + working-directory: codex-rs + steps: + - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.0.1 + with: + persist-credentials: false + fetch-depth: 0 + + - name: Set up Rust toolchain + uses: dtolnay/rust-toolchain@e081816240890017053eacbb1bdf337761dc5582 # 1.95.0 + with: + components: rustfmt, clippy + + # linux-sandbox's build.rs links libcap through pkg-config. + - name: Install build libraries + working-directory: ${{ github.workspace }} + run: sudo apt-get update && sudo apt-get install -y libcap-dev pkg-config libasound2-dev + + # Directory names are not package names (app-server-protocol is the + # package codex-app-server-protocol) and crates nest (codex-rs/ext/skills), + # so each changed file maps to the package whose manifest directory is + # the longest prefix of its path. A workspace manifest change rebuilds + # every package. + - name: Packages changed against fork/main + id: crates + shell: bash + run: | + set -euo pipefail + base="$(git merge-base HEAD origin/fork/main 2>/dev/null || git merge-base HEAD fork/main)" + mapfile -t files < <(git diff --name-only "$base"...HEAD) + all=false + for f in "${files[@]}"; do + case "$f" in + codex-rs/Cargo.toml|codex-rs/Cargo.lock) all=true ;; + esac + done + if $all; then + mapfile -t packages < <(cargo metadata --no-deps --format-version 1 \ + | jq -r '.packages[].name' | sort -u) + else + mapfile -t packages < <(cargo metadata --no-deps --format-version 1 \ + | python3 "${GITHUB_WORKSPACE}/.github/scripts/fork-changed-packages.py" "${files[@]}") + fi + echo "changed: ${packages[*]:-none}" + { + echo "list<> "$GITHUB_OUTPUT" + + # v8's build.rs otherwise downloads librusty_v8 from denoland, which does + # not publish the ptrcomp_sandbox profile this tree expects. This fetches + # the Codex-built artifacts from the upstream release and verifies them + # against the in-tree checksum manifest, the same as fork-release. + - name: Configure rusty_v8 artifact overrides and verify checksums + uses: ./.github/actions/setup-rusty-v8 + with: + target: x86_64-unknown-linux-gnu + + # codex-voice-host is excluded: it is the only package pulling in GStreamer, + # and it requires gstreamer-1.0 >= 1.28. Ubuntu 24.04 ships 1.24, so no + # apt package satisfies it. Upstream never builds it with cargo either; it + # builds //codex-rs/voice-host with Bazel against a bundled GStreamer. + - name: cargo check + run: cargo check --workspace --all-targets --exclude codex-voice-host + + - name: cargo fmt + shell: bash + run: | + set -euo pipefail + while IFS= read -r crate; do + [[ -z "$crate" ]] && continue + cargo fmt -p "$crate" -- --check + done <<< "${{ steps.crates.outputs.list }}" + + - name: cargo clippy + shell: bash + run: | + set -euo pipefail + while IFS= read -r crate; do + [[ -z "$crate" ]] && continue + cargo clippy -p "$crate" --all-targets -- -D warnings + done <<< "${{ steps.crates.outputs.list }}" + + - name: cargo test + shell: bash + run: | + set -euo pipefail + while IFS= read -r crate; do + [[ -z "$crate" ]] && continue + cargo test -p "$crate" + done <<< "${{ steps.crates.outputs.list }}"