Skip to content

fix: instantiate rsr-template placeholders left generic from scaffold… #35

fix: instantiate rsr-template placeholders left generic from scaffold…

fix: instantiate rsr-template placeholders left generic from scaffold… #35

Workflow file for this run

# SPDX-License-Identifier: MPL-2.0
#
# chapel-ci — strict CI gates for the OPTIONAL Chapel mass-panic harness.
#
# The Rust binary stands alone (USB-stick-portable, single-machine). chapel/ is
# a detachable multi-machine harness on top. This workflow exercises the harness
# and the Rust↔Chapel contract surface.
#
# **Why an aggregator gate?** The 6 gate jobs are path-filtered (they only do
# real work when chapel/** or the Rust contract files change). But path-filtered
# workflows that don't trigger leave required status checks "expected but not
# reported" — which blocks unrelated PRs from merging when the gates are in
# the Base ruleset. Solution: a single `chapel-ci-gate` job that ALWAYS runs
# and aggregates. The ruleset requires only the gate. The gate reports:
# - SUCCESS immediately if no chapel-relevant paths changed.
# - SUCCESS if all 6 underlying jobs succeeded on a relevant change.
# - FAILURE if any underlying job failed.
#
# Six strict jobs (no continue-on-error anywhere):
# 1. chapel-parse-check — chpl --parse-only on every module
# 2. chapel-build — chpl build of mass-panic + smoke (no toolbox)
# 3. chapel-smoke — chapel/smoke/two_repo_smoke (Chapel data flow)
# 4. chapel-e2e — mass-panic -nl 1 on a synthetic 2-repo manifest
# True -nl 2 requires CHPL_COMM=gasnet which the
# stock .deb doesn't ship; tracked for Wave 2.
# 5. chapel-cli-contract — panic-attack describe-contract vs expected fixture
# 6. chapel-rust-diff — rayon assemblyline vs Chapel single-locale parity
#
# Plus the always-on aggregator: `chapel-ci-gate`.
#
# Wave 2 hardening tracker: SHA-pin the Chapel 2.8.0 .deb download. Today the
# workflow trusts the HTTPS endpoint at chapel-lang/chapel releases.
name: chapel-ci
on:
push:
branches: [main]
pull_request:
permissions:
contents: read
concurrency:
group: chapel-ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
CHAPEL_VERSION: "2.8.0"
CHAPEL_DEB_URL: "https://github.com/chapel-lang/chapel/releases/download/2.8.0/chapel-2.8.0-1.ubuntu22.amd64.deb"
jobs:
detect-relevant-changes:
name: detect-relevant-changes
runs-on: ubuntu-22.04
outputs:
relevant: ${{ steps.f.outputs.relevant }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 2
- id: f
name: Detect chapel-relevant paths
run: |
set -euo pipefail
BASE="${{ github.event.pull_request.base.sha || github.event.before }}"
if [[ -z "$BASE" || "$BASE" == "0000000000000000000000000000000000000000" ]]; then
# First push or detached state — be safe and run the full gate.
echo "relevant=true" >> "$GITHUB_OUTPUT"
echo "detect: BASE missing/zero — treating as relevant"
exit 0
fi
git fetch origin "$BASE" --depth=1 2>/dev/null || true
CHANGED=$(git diff --name-only "$BASE" HEAD || true)
echo "Changed files:"
echo "$CHANGED"
if echo "$CHANGED" | grep -qE '^(chapel/|Justfile$|\.github/workflows/chapel-ci\.yml$|src/main\.rs$|src/types\.rs$|Cargo\.toml$|Cargo\.lock$)'; then
echo "relevant=true" >> "$GITHUB_OUTPUT"
echo "detect: chapel-relevant paths changed — running gates"
else
echo "relevant=false" >> "$GITHUB_OUTPUT"
echo "detect: no chapel-relevant paths — gates skipped via if-guard"
fi
chapel-parse-check:
name: chapel-parse-check
needs: detect-relevant-changes
if: needs.detect-relevant-changes.outputs.relevant == 'true'
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install Chapel ${{ env.CHAPEL_VERSION }}
run: |
set -euo pipefail
sudo apt-get update -qq
sudo apt-get install -y libunwind-dev
curl -fsSL --retry 3 -o /tmp/chapel.deb "${{ env.CHAPEL_DEB_URL }}"
sudo apt-get install -y /tmp/chapel.deb
chpl --version
- name: Parse every Chapel module
working-directory: chapel
run: |
set -euo pipefail
chpl --parse-only src/MassPanic.chpl src/Protocol.chpl src/Imaging.chpl src/Temporal.chpl
chpl --parse-only smoke/two_repo_smoke.chpl src/Protocol.chpl src/Imaging.chpl
chapel-build:
name: chapel-build
needs: [detect-relevant-changes, chapel-parse-check]
if: needs.detect-relevant-changes.outputs.relevant == 'true'
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install Chapel ${{ env.CHAPEL_VERSION }}
run: |
set -euo pipefail
sudo apt-get update -qq
sudo apt-get install -y libunwind-dev
curl -fsSL --retry 3 -o /tmp/chapel.deb "${{ env.CHAPEL_DEB_URL }}"
sudo apt-get install -y /tmp/chapel.deb
chpl --version
- name: Build mass-panic + smoke (no toolbox)
working-directory: chapel
run: |
set -euo pipefail
chpl src/MassPanic.chpl src/Protocol.chpl src/Imaging.chpl src/Temporal.chpl -o mass-panic
chpl smoke/two_repo_smoke.chpl src/Protocol.chpl src/Imaging.chpl -o smoke/two_repo_smoke
- name: Upload Chapel artefacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: chapel-binaries
path: |
chapel/mass-panic
chapel/smoke/two_repo_smoke
retention-days: 1
chapel-smoke:
name: chapel-smoke
needs: [detect-relevant-changes, chapel-build]
if: needs.detect-relevant-changes.outputs.relevant == 'true'
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install Chapel ${{ env.CHAPEL_VERSION }}
run: |
set -euo pipefail
sudo apt-get update -qq
sudo apt-get install -y libunwind-dev
curl -fsSL --retry 3 -o /tmp/chapel.deb "${{ env.CHAPEL_DEB_URL }}"
sudo apt-get install -y /tmp/chapel.deb
- name: Download Chapel artefacts
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
name: chapel-binaries
path: chapel/
- name: Restore exec bits
run: chmod +x chapel/mass-panic chapel/smoke/two_repo_smoke
- name: Run two_repo_smoke
run: ./chapel/smoke/two_repo_smoke
chapel-e2e:
name: chapel-e2e
needs: [detect-relevant-changes, chapel-build]
if: needs.detect-relevant-changes.outputs.relevant == 'true'
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install Chapel ${{ env.CHAPEL_VERSION }}
run: |
set -euo pipefail
sudo apt-get update -qq
sudo apt-get install -y libunwind-dev
curl -fsSL --retry 3 -o /tmp/chapel.deb "${{ env.CHAPEL_DEB_URL }}"
sudo apt-get install -y /tmp/chapel.deb
- name: Download Chapel artefacts
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
name: chapel-binaries
path: chapel/
- name: Restore exec bits
run: chmod +x chapel/mass-panic
- name: End-to-end -nl 1 exercise
run: |
set -euo pipefail
WORK=$(mktemp -d /tmp/chapel-e2e-XXXXXX)
trap 'rm -rf "$WORK"' EXIT
mkdir -p "$WORK/corpus/repo-alpha/src" "$WORK/corpus/repo-beta/src"
echo 'pub unsafe fn a() {}' > "$WORK/corpus/repo-alpha/src/lib.rs"
echo 'pub unsafe fn b() {}' > "$WORK/corpus/repo-beta/src/lib.rs"
for d in repo-alpha repo-beta; do
(cd "$WORK/corpus/$d" && git init -q && git add -A && git -c user.email=ci@example.com -c user.name=ci commit -q -m init)
done
./chapel/mass-panic --repoDirectory="$WORK/corpus" --numLocales=1 --quiet --outputDir="$WORK/out"
ls "$WORK/out"/system-image-*.json >/dev/null
echo "chapel-e2e: PASS"
chapel-cli-contract:
name: chapel-cli-contract
needs: detect-relevant-changes
if: needs.detect-relevant-changes.outputs.relevant == 'true'
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: dtolnay/rust-toolchain@4be9e76fd7c4901c61fb841f559994984270fce7 # stable
- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-chapel-cli-contract-${{ hashFiles('Cargo.lock') }}
- name: Build panic-attack
run: cargo build --release --locked
- name: Run contract gate
run: ./chapel/tests/contract_check.sh
chapel-rust-diff:
name: chapel-rust-diff
needs: [detect-relevant-changes, chapel-build]
if: needs.detect-relevant-changes.outputs.relevant == 'true'
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: dtolnay/rust-toolchain@4be9e76fd7c4901c61fb841f559994984270fce7 # stable
- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-chapel-rust-diff-${{ hashFiles('Cargo.lock') }}
- name: Install Chapel ${{ env.CHAPEL_VERSION }}
run: |
set -euo pipefail
sudo apt-get update -qq
sudo apt-get install -y libunwind-dev
curl -fsSL --retry 3 -o /tmp/chapel.deb "${{ env.CHAPEL_DEB_URL }}"
sudo apt-get install -y /tmp/chapel.deb
- name: Download Chapel artefacts
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
name: chapel-binaries
path: chapel/
- name: Restore exec bits
run: chmod +x chapel/mass-panic
- name: Build panic-attack
run: cargo build --release --locked
- name: rayon vs Chapel single-locale aggregate parity
run: ./chapel/tests/rayon_vs_chapel_diff.sh
# Always-on aggregator. This is the ONLY job listed in the Base ruleset's
# required_status_checks rule. If detect-relevant-changes determined nothing
# in this PR touches Chapel-relevant paths, the gate passes immediately
# (the six per-task jobs above skip via their `if:` guard). If a relevant
# change is present, the gate inspects each job's result and only passes
# when ALL six succeeded.
chapel-ci-gate:
name: chapel-ci-gate
needs:
- detect-relevant-changes
- chapel-parse-check
- chapel-build
- chapel-smoke
- chapel-e2e
- chapel-cli-contract
- chapel-rust-diff
if: always()
runs-on: ubuntu-22.04
steps:
- name: Aggregate chapel-ci results
env:
RELEVANT: ${{ needs.detect-relevant-changes.outputs.relevant }}
R_PARSE: ${{ needs.chapel-parse-check.result }}
R_BUILD: ${{ needs.chapel-build.result }}
R_SMOKE: ${{ needs.chapel-smoke.result }}
R_E2E: ${{ needs.chapel-e2e.result }}
R_CLI: ${{ needs.chapel-cli-contract.result }}
R_DIFF: ${{ needs.chapel-rust-diff.result }}
run: |
set -euo pipefail
echo "detect-relevant-changes.outputs.relevant=$RELEVANT"
printf 'parse-check=%s\nbuild=%s\nsmoke=%s\ne2e=%s\ncli-contract=%s\nrust-diff=%s\n' \
"$R_PARSE" "$R_BUILD" "$R_SMOKE" "$R_E2E" "$R_CLI" "$R_DIFF"
if [[ "$RELEVANT" != "true" ]]; then
echo "chapel-ci-gate: SKIP (no chapel-relevant paths changed) → PASS"
exit 0
fi
# If detect itself failed, we never confirmed relevance — fail safe.
if [[ "${{ needs.detect-relevant-changes.result }}" != "success" ]]; then
echo "chapel-ci-gate: detect-relevant-changes did not succeed → FAIL"
exit 1
fi
fail=0
for r in "$R_PARSE" "$R_BUILD" "$R_SMOKE" "$R_E2E" "$R_CLI" "$R_DIFF"; do
case "$r" in
success) ;;
*) fail=$((fail + 1)) ;;
esac
done
if [[ $fail -gt 0 ]]; then
echo "chapel-ci-gate: $fail dependent job(s) did not succeed → FAIL"
exit 1
fi
echo "chapel-ci-gate: all six gates green → PASS"