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
111 changes: 111 additions & 0 deletions .github/workflows/llvm-inprocess.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# CI arm for the in-process LLVM backend (#7241, merged in #7301).
#
# The GC knob kill-policy (CLAUDE.md) demands every shipped mode be exercised
# by CI or deleted; this job is the exercise for `PERRY_LLVM_INPROCESS`.
# Each step asserts its subject was LIVE (liveness line, diff verdict) rather
# than merely that nothing threw — see "Four ways a gate can be unable to
# fail". NON-REQUIRED until it has run green once; promote afterwards
# (a new gate has never been green, so promoting first blocks every PR).
Comment on lines +7 to +8

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files '.github/workflows/*' | sed -n '1,120p'

echo
echo "== workflow excerpt =="
if [ -f .github/workflows/llvm-inprocess.yml ]; then
  nl -ba .github/workflows/llvm-inprocess.yml | sed -n '1,120p'
fi

echo
echo "== relevant branch protection/workflows mentions =="
rg -n -C 3 'llvm-inprocess|required_status_checks|check-stale|paths:|runs-on|continue-on-error|cancel-current|main' .github/workflows/llvm-inprocess.yml .github/workflows || true

Repository: PerryTS/perry

Length of output: 1016


🌐 Web query:

GitHub required status checks blocked on files matching path filter changed paths required workflow not scheduled

💡 Result:

When you use path filters (such as paths or paths-ignore) in a GitHub Actions workflow that is configured as a required status check, the pull request may become permanently blocked from merging if the workflow is skipped [1][2][3]. This happens because GitHub expects a status report from the required workflow; if the workflow is skipped due to path filtering, it does not execute, does not report a status, and therefore remains in a "Pending" or "Waiting" state indefinitely [1][4][3]. To resolve this issue, GitHub and industry best practices recommend avoiding the use of trigger-level path filters for workflows that are required for branch protection [1][2]. Instead, use the following approaches to ensure a status check is always reported: 1. Remove trigger-level path filters: Remove the paths or paths-ignore configuration from the on block of your workflow. This ensures the workflow runs for every pull request, allowing it to always report a status [1][2]. 2. Move filtering inside the workflow: Use a dedicated "gate" or "check" step inside the workflow to determine if relevant files have changed [2][5]. You can use community tools (such as dorny/paths-filter) to detect changed files and set output variables [2][5]. 3. Use conditional job execution: Use the if conditional on your jobs to execute only when necessary [2][5]. For example, you can have a "gate" job that runs for every pull request and outputs whether tests should run. Downstream jobs can then check this output using if conditions to decide whether to execute or skip [2][5]. 4. Ensure a status is always reported: If you have a workflow that only runs conditionally, you must ensure that even when the primary "work" jobs are skipped, at least one job still executes to report a successful status back to GitHub [2][5]. This can be achieved by adding a "dummy" or "gate" job that uses if: always() and depends on the previous filtering step to ensure it reports a "success" even if the actual task jobs are skipped [2][5]. This ensures the required check always satisfies the branch protection rule [2][5]. By moving logic from the workflow trigger to internal job conditionals, you maintain the ability to skip expensive tasks while guaranteeing that the status check required by your branch protection settings is always generated [2][5].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow excerpt =="
if [ -f .github/workflows/llvm-inprocess.yml ]; then
  awk '{printf "%6d\t%s\n", NR, $0}' .github/workflows/llvm-inprocess.yml | sed -n '1,120p'
fi

echo
echo "== workflow occurrences =="
if [ -f .github/workflows/llvm-inprocess.yml ]; then
  grep -nE 'on:|pull_request|push|paths:|paths-ignore|continue-on-error|runs-on|fail-fast|benchmarks/app-patterns|corpus|RS4GC|assert|batch\.ts' .github/workflows/llvm-inprocess.yml || true
fi

echo
echo "== branch protection / required check mentions =="
rg -n -C 2 'llvm-inprocess|required_status_checks|check-stale|status checks|code quality|branch protection|branches_to_protect|branches' .github || true

Repository: PerryTS/perry

Length of output: 16877


Make llvm-inprocess a required check triggered for every PR.

The workflow is currently non-required. This contradicts the CI requirement that gates be required branch-protection contexts. Moving the path decision into a job-level filter avoids skipping the required status when the changed files only include benchmarks/app-patterns/kernels/batch.ts. Add the workflow check to the main branch protection rule when promoting it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/llvm-inprocess.yml around lines 7 - 8, Promote the
llvm-inprocess workflow to a required check for every pull request, and add its
check context to the main branch-protection rule. Move path filtering from the
workflow trigger to a job-level filter so the required status is emitted even
when only benchmarks/app-patterns/kernels/batch.ts changes.

Source: Coding guidelines

name: llvm-inprocess

# No trigger-level `paths:` — deliberately. A required check whose workflow
# is path-filtered at the trigger never CREATES a check run for PRs outside
# those paths, so the required context sits "waiting" forever and blocks the
# merge (the promotion trap CodeRabbit flagged on #7304). Filtering lives in
# the `changes` job instead: a job skipped by `if:` still reports a check
# run (conclusion: skipped), which branch protection accepts.
on:
pull_request:
push:
branches: [main]

concurrency:
group: llvm-inprocess-${{ github.ref }}
# Gate-trap 3: cancel superseded PR runs, but NEVER cancel main runs — a
# busy merge day would otherwise starve the gate to zero executions.
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
# Cheap relevance filter via the PR files API (no checkout, no third-party
# action). Pushes to main always run — main executions are the gate's
# anchor and the promotion prerequisite.
changes:
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
pull-requests: read
outputs:
relevant: ${{ steps.filter.outputs.relevant }}
steps:
- id: filter
env:
GH_TOKEN: ${{ github.token }}
run: |
if [ "${{ github.event_name }}" = "push" ]; then
echo "relevant=true" >> "$GITHUB_OUTPUT"
exit 0
fi
files=$(gh api "repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/files" --paginate --jq '.[].filename')
if echo "$files" | grep -qE '^(crates/perry-codegen/|crates/perry/src/commands/compile/|experiments/llvm-inprocess-spike/|benchmarks/app-patterns/kernels/batch\.ts$|\.github/workflows/llvm-inprocess\.yml$)'; then
echo "relevant=true" >> "$GITHUB_OUTPUT"
else
echo "relevant=false" >> "$GITHUB_OUTPUT"
fi

native-backend:
needs: changes
if: needs.changes.outputs.relevant == 'true'
runs-on: macos-15
timeout-minutes: 90
steps:
- uses: actions/checkout@v4

- name: Install LLVM 22 (pinned major — fail loudly on drift)
run: |
set -euo pipefail
brew install llvm@22 2>/dev/null || brew install llvm
PREFIX="$(brew --prefix llvm@22 2>/dev/null || brew --prefix llvm)"
# llvm-sys 221 requires major 22. If the runner's formula moves on,
# this must go red, not quietly build something else.
"$PREFIX/bin/llvm-config" --version | grep -q '^22\.'
echo "LLVM_SYS_221_PREFIX=$PREFIX" >> "$GITHUB_ENV"

- name: Build with the llvm-inprocess feature
run: |
cargo build --profile perry-dev -p perry -p perry-runtime-static \
-p perry-stdlib-static --features perry/llvm-inprocess

- name: Unit gates (528 incl. corpus construction + RS4GC pin)
run: |
set -euo pipefail
out=$(cargo test --profile perry-dev -p perry-codegen \
--features llvm-inprocess --lib 2>&1) || { echo "$out"; exit 1; }
# The corpus gates must have RUN, not skipped: a checkout missing
# the tracked .ll corpora would otherwise green vacuously.
echo "$out" | grep -q "dialect::tests::corpus_spike ... ok"
echo "$out" | grep -q "dialect::tests::corpus_batch_kernel ... ok"
echo "$out" | grep -q "inprocess::tests::rs4gc_schedules_in_process ... ok"

- name: Native-mode smoke — liveness, behavior parity, object-byte verdicts
run: |
set -euo pipefail
export PERRY_RUNTIME_DIR="$PWD/target/perry-dev"
export PERRY_NO_AUTO_OPTIMIZE=1
BIN=target/perry-dev/perry
SRC=experiments/llvm-inprocess-spike/spike.ts

"$BIN" "$SRC" -o /tmp/spike_text
/tmp/spike_text > /tmp/text.out

PERRY_LLVM_INPROCESS=native "$BIN" "$SRC" -o /tmp/spike_native 2> /tmp/native.err
grep -q "in-process LLVM backend active" /tmp/native.err
/tmp/spike_native > /tmp/native.out
cmp /tmp/text.out /tmp/native.out

PERRY_LLVM_INPROCESS=diff "$BIN" "$SRC" -o /tmp/spike_diff 2> /tmp/diff.err
grep -q "ir-diff. OK" /tmp/diff.err

PERRY_LLVM_INPROCESS=diff PERRY_CODEGEN_UNITS=3 "$BIN" \
benchmarks/app-patterns/kernels/batch.ts -o /tmp/batch_diff 2> /tmp/diffu.err
grep -q "ir-diff. OK.*3 units" /tmp/diffu.err
7 changes: 7 additions & 0 deletions changelog.d/7304-llvm-inprocess-ci-arm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CI arm for the in-process LLVM backend (#7301 follow-up, kill-policy): a
path-filtered macOS job builds the `llvm-inprocess` feature against a
loudly-pinned LLVM 22, runs the perry-codegen suite asserting the corpus
and RS4GC gates actually ran, and smokes `PERRY_LLVM_INPROCESS=native`
end-to-end — liveness line, behavior parity with the text arm, and
object-byte `=diff` verdicts for a single module and a forced 3-unit
split. Lands non-required; promote after first green.
Loading