diff --git a/.github/workflows/fork-ci.yml b/.github/workflows/fork-ci.yml index 693d41cfcf35..4eed6177a0dc 100644 --- a/.github/workflows/fork-ci.yml +++ b/.github/workflows/fork-ci.yml @@ -65,6 +65,9 @@ jobs: echo "list<> "$GITHUB_OUTPUT" # v8's build.rs otherwise downloads librusty_v8 from denoland, which does @@ -92,13 +95,46 @@ jobs: cargo fmt -p "$crate" -- --check done <<< "${{ steps.crates.outputs.list }}" + # -D warnings would fail the PR on upstream lint debt in files it never + # touched, and a fork patch must not have to fix that. Clippy runs without + # it, and only a warning or error whose primary span is in a file this PR + # changed fails the build. Compile errors are fatal regardless, which + # `cargo check` above already enforces. - name: cargo clippy shell: bash run: | set -euo pipefail + printf '%s\n' "${{ steps.crates.outputs.files }}" | sed 's|^codex-rs/||' > /tmp/changed-files while IFS= read -r crate; do [[ -z "$crate" ]] && continue - cargo clippy -p "$crate" --all-targets -- -D warnings + cargo clippy -p "$crate" --all-targets --message-format=json -- -W clippy::all \ + > "/tmp/clippy-${crate}.json" || true + # --slurpfile yields an array of strings. Iterating each element + # again (`[$changed[][]]`) is a jq runtime error, and jq exits 0 on + # those, so the gate would pass every PR. `any` compares strings + # directly. stderr goes to a file synchronously: a process + # substitution can still be writing when the check runs, which + # would let a jq error pass again. + rm -f /tmp/jq-err + offenders="$(jq -r --slurpfile changed <(jq -R . /tmp/changed-files) ' + select(.reason == "compiler-message") + | .message + | select(.level == "warning" or .level == "error") + | . as $m + | ($m.spans[] | select(.is_primary)) as $s + | select(any($changed[]; . == $s.file_name)) + | "\($s.file_name):\($s.line_start):\($s.column_start): \($m.level): \($m.message)" + ' "/tmp/clippy-${crate}.json" 2>/tmp/jq-err)" + if [[ -s /tmp/jq-err ]]; then + cat /tmp/jq-err >&2 + echo "jq failed to read the clippy output" >&2 + exit 1 + fi + if [[ -n "$offenders" ]]; then + echo "$offenders" + echo "clippy findings in files this PR changes" >&2 + exit 1 + fi done <<< "${{ steps.crates.outputs.list }}" - name: cargo test @@ -107,5 +143,13 @@ jobs: set -euo pipefail while IFS= read -r crate; do [[ -z "$crate" ]] && continue - cargo test -p "$crate" + # packaged_daemon_bootstrap_seeds_local_package asserts + # autoUpdateEnabled == false, but default_auto_update_enabled() + # returns true in this tree. It fails on unmodified fork/main, so + # it is upstream drift rather than anything a fork PR introduced. + extra=() + if [[ "$crate" == "codex-cli" ]]; then + extra+=(-- --skip packaged_daemon_bootstrap_seeds_local_package) + fi + cargo test -p "$crate" "${extra[@]}" done <<< "${{ steps.crates.outputs.list }}"