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
37 changes: 37 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,40 @@ jobs:
cd python
pip install -e '.[dev]'
python -m pytest -v

# Consumer-shaped verification: install the reactor into a FRESH local
# repository and run a standalone downstream project (no parent POM, no
# reactor classes) against ONLY those artifacts — the same way a real
# consumer resolves from Maven Central. In-repo tests run against the
# reactor and cannot see a partial publish, a missing coordinate, or
# parent-POM coupling; this job can (the 1.0.0 incident).
consumer-verification:
if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main'
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
cache: 'maven'

- name: Install reactor into a fresh local repository
run: |
echo "FRESH=$RUNNER_TEMP/m2-consumer" >> "$GITHUB_ENV"
mvn -B install -DskipTests -Dmaven.repo.local="$RUNNER_TEMP/m2-consumer"

- name: Resolve the reactor version
run: |
VERSION=$(mvn -B -q help:evaluate -Dexpression=project.version -DforceStdout)
echo "VERSION=$VERSION" >> "$GITHUB_ENV"

- name: Consumer test path (in-process mutation loop)
run: mvn -B test -f examples/consumer-standalone/pom.xml -Dmaven.repo.local="$FRESH" -Dmutator.version="$VERSION"

- name: Consumer fork path (plugin mutate, scoped to one class)
run: mvn -B test-compile io.github.wpunit13:spark-mutation-testing-maven-plugin:"$VERSION":mutate -f examples/consumer-standalone/pom.xml -Dmaven.repo.local="$FRESH" -Dmutator.version="$VERSION" -Dtest=SimpleReadWriteTest
19 changes: 13 additions & 6 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,11 @@ jobs:
inputs.jobs == 'smoke-only')
runs-on: ubuntu-latest
steps:
- name: Checkout repository (verify-release.sh lives in the tagged commit)
uses: actions/checkout@v4
with:
ref: refs/tags/v${{ needs.guard.outputs.version }}

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
Expand Down Expand Up @@ -251,20 +256,22 @@ jobs:
print("bundled jars:", jars)
PY

- name: Resolve plugin + bundle from Maven Central
# The FULL consumer-facing coordinate set, not just two spot checks:
# the 1.0.0 release published a subset of the modules and the plugin
# resolved a coordinate that was never published — every downstream
# consumer's CI-grade path died while this smoke test stayed green on
# its two-artifact spot check.
- name: Resolve the full release coordinate set from Maven Central
env:
VERSION: ${{ needs.guard.outputs.version }}
run: |
for _ in $(seq 1 30); do
if mvn -B -q dependency:get \
-Dartifact="io.github.wpunit13:spark-mutation-testing-maven-plugin:$VERSION" \
&& mvn -B -q dependency:get \
-Dartifact="io.github.wpunit13:interceptor-bundle-spark-3.5_2.13:$VERSION"; then
if bash scripts/verify-release.sh "$VERSION"; then
echo "Central resolution OK"
exit 0
fi
echo "Not on Central yet (attempt $_/30) — waiting 60s..."
sleep 60
done
echo "ERROR: artifacts not resolvable from Central after 30 minutes" >&2
echo "ERROR: release coordinates not resolvable from Central after 30 minutes" >&2
exit 1
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,21 @@ trait PlanMutatorShim {
* logical query.
*/
def canonicalExprSig(node: LogicalPlan, operatorType: OperatorType): String

/**
* The set of expression fingerprints that make up this node's site:
* per-conjunct sigs for Filter/Join conditions, per-expression sigs for
* Aggregate/Window/Project. The optimizer can only REMOVE expressions
* (pruning, conversion) or ADD condition conjuncts (pushdown), so a
* surviving site's set always INTERSECTS the discovery-time set — while a
* different site built over a differently-typed source (e.g. an implicit
* CAST inserted for a JSON-inferred BIGINT vs an INT LocalRelation)
* produces a disjoint set. Site-identity checks (viability filtering,
* identity fallback) use this intersection to tell "the same site,
* reshaped" from "a different site that merely looks similar".
*
* Default: empty set (test fakes). Both real shim implementations override
* this; the cross-version golden guard exercises the override.
*/
def exprSigSet(node: LogicalPlan, operatorType: OperatorType): Set[String] = Set.empty
}
Loading
Loading