Skip to content

Commit 55562c9

Browse files
committed
Resolve middlewares per context and run the matrix on PHP 8.4 and 8.5
composer.json no longer commits path repositories. The reusable interop workflow checks out the calling middleware (the originating repo and ref for a pull request, forks included), names that checkout after the PR branch, and requires the package at dev-<that-branch> through a path repo, so it follows whatever branch is under review with nothing hardcoded. The self-test ci.yml declares no repositories and resolves from Packagist. Local make injects path repos to the sibling working copies into a gitignored composer.run.json so the committed file stays clean. Runtimes move to PHP 8.4/8.5 matrix, Java 21, and the current action versions.
1 parent fe8497a commit 55562c9

8 files changed

Lines changed: 110 additions & 165 deletions

File tree

.github/workflows/ci.yml

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,39 @@
11
name: ci
22

3-
# The harness's own self-test. Unlike the reusable interop.yml (which repoints the path repo at a
4-
# consumer PR), this builds the harness against its declared path repos to the sibling middleware repos,
5-
# so a change to the harness itself is exercised end-to-end on every push / PR.
3+
# The harness's own self-test, on PHP 8.4 and 8.5. The committed composer.json declares no
4+
# repositories and requires the middlewares at @dev, so this resolves them from Packagist. It turns
5+
# green once the middleware changes the harness exercises are released to their main branches.
66
on:
77
push:
88
pull_request:
99

1010
jobs:
1111
self-test:
1212
runs-on: ubuntu-latest
13+
strategy:
14+
fail-fast: false
15+
matrix:
16+
php: ['8.4', '8.5']
17+
name: PHP ${{ matrix.php }}
1318
steps:
1419
- name: Checkout harness
15-
uses: actions/checkout@v4
16-
17-
# The sibling middlewares the harness's composer.json path repos point at (../<name>).
18-
- name: Checkout http-wsse-middleware
19-
uses: actions/checkout@v4
20-
with:
21-
repository: php-soap/http-wsse-middleware
22-
path: ../http-wsse-middleware
23-
- name: Checkout psr18-attachments-middleware
24-
uses: actions/checkout@v4
25-
with:
26-
repository: php-soap/psr18-attachments-middleware
27-
path: ../psr18-attachments-middleware
20+
uses: actions/checkout@v7
2821

2922
- name: Setup PHP
3023
uses: shivammathur/setup-php@v2
3124
with:
32-
php-version: '8.4'
25+
php-version: ${{ matrix.php }}
3326
extensions: dom, openssl, intl, gmp, bcmath
3427
coverage: none
3528

36-
- name: Set up JDK 17
37-
uses: actions/setup-java@v4
29+
- name: Set up JDK 21
30+
uses: actions/setup-java@v5
3831
with:
3932
distribution: temurin
40-
java-version: '17'
33+
java-version: '21'
4134

4235
- name: Cache Maven repository
43-
uses: actions/cache@v4
36+
uses: actions/cache@v6
4437
with:
4538
path: ~/.m2
4639
key: ${{ runner.os }}-m2-${{ hashFiles('oracle/pom.xml') }}

.github/workflows/interop.yml

Lines changed: 48 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,136 +1,93 @@
11
name: interop
22

3-
# Reusable cross-stack interop workflow. A consumer middleware repo calls this from its own PR CI to
4-
# run the php-soap interop suite (PHP middleware <-> Dockerised WSS4J oracle) against the EXACT PR commit
5-
# under review. The override is the same composer path-repository mechanism used for local dev: the
6-
# harness's path repo is simply repointed at the PR checkout, so local and PR runs share one code path.
3+
# Reusable cross-stack interop workflow. A middleware repo calls this from its own PR CI to run the
4+
# php-soap interop suite (PHP middleware against a Dockerised WSS4J oracle) on the exact commit under
5+
# review. Nothing about the branch or repository is hardcoded: the caller is checked out by the standard
6+
# action, which for a pull request resolves the originating commit (forks included). That checkout is the
7+
# package source, so the workflow works on whatever branch is being tested.
78
on:
89
workflow_call:
910
inputs:
1011
package:
11-
description: 'Composer package name of the consumer middleware (e.g. php-soap/psr18-wsse-middleware).'
12+
description: 'Composer package name of the calling middleware, e.g. php-soap/psr18-wsse-middleware.'
1213
required: true
1314
type: string
1415
suites:
15-
description: 'PHPUnit testsuite(s) to run (e.g. wsse or attachments).'
16+
description: 'PHPUnit testsuite(s) to run, e.g. wsse or attachments.'
17+
required: true
18+
type: string
19+
php-versions:
20+
description: 'JSON array of PHP versions to run the matrix on.'
1621
required: false
1722
type: string
18-
default: 'wsse'
23+
default: '["8.4", "8.5"]'
1924

2025
jobs:
2126
interop:
2227
runs-on: ubuntu-latest
28+
strategy:
29+
fail-fast: false
30+
matrix:
31+
php: ${{ fromJSON(inputs.php-versions) }}
32+
name: ${{ inputs.suites }} on PHP ${{ matrix.php }}
2333
steps:
24-
# The interop harness (this repo): oracle, Dockerfile, certs, tests, harness composer.json. Its
25-
# composer.json declares path repos to ../<sibling-middleware>; we lay the checkouts out to match.
26-
- name: Checkout interop harness
27-
uses: actions/checkout@v4
34+
# The calling middleware at the commit under review. A plain checkout in a reusable workflow pulls
35+
# the caller; for a pull request it resolves the originating repository and ref (forks included).
36+
- name: Checkout the middleware under test
37+
uses: actions/checkout@v7
2838
with:
29-
repository: php-soap/java-interop
30-
path: harness
39+
path: middleware
3140

32-
# The consumer PR code, checked out into the sibling path the harness already points at. In a
33-
# reusable workflow a plain checkout pulls the CALLER repo = the PR commit under review, so the
34-
# harness's existing path repo now resolves to the PR working copy. ONE mechanism, repointed.
35-
- name: Checkout consumer PR
36-
uses: actions/checkout@v4
41+
- name: Checkout the interop harness
42+
uses: actions/checkout@v7
3743
with:
38-
path: consumer
39-
40-
# The OTHER sibling middleware the harness path repos reference (the one not under review) is
41-
# checked out at its expected released/main version so the harness graph still resolves.
42-
- name: Checkout sibling http-wsse-middleware
43-
if: ${{ inputs.package != 'php-soap/psr18-wsse-middleware' }}
44-
uses: actions/checkout@v4
45-
with:
46-
repository: php-soap/http-wsse-middleware
47-
path: http-wsse-middleware
48-
- name: Checkout sibling psr18-attachments-middleware
49-
if: ${{ inputs.package != 'php-soap/psr18-attachments-middleware' }}
50-
uses: actions/checkout@v4
51-
with:
52-
repository: php-soap/psr18-attachments-middleware
53-
path: psr18-attachments-middleware
44+
repository: php-soap/java-interop
45+
path: harness
5446

5547
- name: Setup PHP
5648
uses: shivammathur/setup-php@v2
5749
with:
58-
php-version: '8.4'
50+
php-version: ${{ matrix.php }}
5951
extensions: dom, openssl, intl, gmp, bcmath
6052
coverage: none
6153

62-
- name: Set up JDK 17
63-
uses: actions/setup-java@v4
54+
- name: Set up JDK 21
55+
uses: actions/setup-java@v5
6456
with:
6557
distribution: temurin
66-
java-version: '17'
58+
java-version: '21'
6759

6860
- name: Cache Maven repository
69-
uses: actions/cache@v4
61+
uses: actions/cache@v6
7062
with:
7163
path: ~/.m2
7264
key: ${{ runner.os }}-m2-${{ hashFiles('harness/oracle/pom.xml') }}
7365
restore-keys: ${{ runner.os }}-m2-
7466

75-
# Two-step build: jar on the host (cached ~/.m2), then a copy-only docker build (seconds).
76-
- name: Build oracle jar
77-
run: mvn -B -f harness/oracle/pom.xml -DskipTests package
78-
79-
- name: Build oracle image
80-
run: docker build -t java-interop-oracle harness
81-
82-
- name: Generate certs
83-
run: bash harness/certs/generate.sh
84-
85-
- name: Start oracle
67+
- name: Build and start the oracle
8668
run: |
87-
docker run -d --name oracle -p 8080:8080 \
88-
-v "$PWD/harness/certs:/certs" java-interop-oracle
69+
mvn -B -f harness/oracle/pom.xml -DskipTests package
70+
docker build -t java-interop-oracle harness
71+
bash harness/certs/generate.sh
72+
docker run -d --name oracle -p 8080:8080 -v "$PWD/harness/certs:/certs" java-interop-oracle
8973
for i in $(seq 1 30); do
90-
if curl -fsS http://127.0.0.1:8080/health >/dev/null 2>&1; then
91-
echo "oracle healthy"; exit 0
92-
fi
74+
if curl -fsS http://127.0.0.1:8080/health >/dev/null 2>&1; then echo "oracle healthy"; break; fi
9375
sleep 1
9476
done
95-
echo "oracle failed to become healthy"; docker logs oracle; exit 1
96-
97-
# THE OVERRIDE: repoint the harness path repository at the PR checkout, then update only the
98-
# consumer package (+ its deps) from there. A path repository wins over Packagist, so the harness
99-
# vendor/ is built from the PR working copy = the exact commit under review.
100-
#
101-
# Detached-HEAD wrinkle: actions/checkout leaves PR checkouts on a detached HEAD, which can stop
102-
# composer from inferring a branch/version for the path dependency. We pin it explicitly with
103-
# COMPOSER_ROOT_VERSION on the path repo by requiring the alias "*@dev" and letting prefer-stable
104-
# fall through to the path version. To be robust we also alias the detached HEAD to a dev branch.
105-
- name: Override the harness path repo with the PR checkout
106-
working-directory: harness
107-
run: |
108-
# Give the detached PR checkout a real branch name so composer's path version guesser resolves
109-
# a dev-<branch> constraint instead of failing on actions/checkout's bare detached HEAD.
110-
git -C ../consumer checkout -B interop-pr-under-test
111-
112-
# Repoint the SAME named path repo the harness already declares at the PR working copy. This
113-
# reuses the local-dev path-repo mechanism verbatim; only the url changes to the PR commit.
114-
case "${{ inputs.package }}" in
115-
php-soap/psr18-wsse-middleware) REPO=wsse-middleware ;;
116-
php-soap/psr18-attachments-middleware) REPO=attachments-middleware ;;
117-
*) echo "Unsupported package: ${{ inputs.package }}"; exit 1 ;;
118-
esac
119-
composer config "repositories.$REPO" \
120-
'{"type":"path","url":"../consumer","options":{"symlink":false}}'
121-
122-
# Require the package at "*@dev" so the path version is eligible, then a full update resolves
123-
# the whole graph (the harness ships no lock file, so a partial update is not possible).
124-
composer require "${{ inputs.package }}:*@dev" --no-update
125-
composer update --with-all-dependencies
12677
127-
# Prove the path version (not a Packagist release) was selected.
128-
- name: Verify PR version is in use
78+
# Point the harness at the checked-out middleware. The checkout above is the commit under test, so a
79+
# path repository to it is the source; composer derives the package version from the checkout's branch.
80+
# Give the (possibly detached) PR checkout that branch name so the derived dev-<branch> is unambiguous.
81+
- name: Resolve the middleware from the checkout
12982
working-directory: harness
83+
env:
84+
PACKAGE: ${{ inputs.package }}
85+
BRANCH: ${{ github.head_ref || github.ref_name }}
13086
run: |
131-
composer show "${{ inputs.package }}"
132-
composer show "${{ inputs.package }}" | grep -E 'source|dist' \
133-
&& echo "Resolved from path repo (PR checkout)."
87+
git -C ../middleware checkout -B "$BRANCH"
88+
composer config repositories.middleware path ../middleware
89+
composer require "$PACKAGE:dev-$BRANCH" --no-update
90+
composer update --with-all-dependencies --no-interaction --no-progress
13491
13592
- name: Run interop tests
13693
working-directory: harness

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
/vendor/
22
/composer.lock
3+
/composer.run.json
4+
/composer.run.lock
35
/.phpunit.cache/
46
/oracle/target/
57
/oracle/dependency-reduced-pom.xml

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Single-stage image: the fat jar is built on the host/CI with `mvn -f oracle/pom.xml package`
22
# (Maven cache warm in ~/.m2) BEFORE `docker build`, so the image build itself is just a copy and
33
# stays in the seconds range. See README.md for the two-step build.
4-
FROM eclipse-temurin:17-jre
4+
FROM eclipse-temurin:21-jre
55

66
# curl backs the compose healthcheck (`GET /health`); install it explicitly so the probe does not
77
# depend on whatever the base image happens to ship.

Makefile

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,27 @@
44
# One command: make interop (full suite)
55
# make interop SUITE=wsse (one testsuite: wsse | attachments)
66

7-
MVN_IMG := maven:3-eclipse-temurin-17
7+
MVN_IMG := maven:3-eclipse-temurin-21
88
JAR := oracle/target/java-interop-oracle.jar
99

1010
# Optional: SUITE=wsse|attachments restricts the run to one testsuite.
1111
SUITE :=
1212
SUITE_ARG = $(if $(SUITE),--testsuite $(SUITE),)
1313

14+
# The committed composer.json declares NO repositories — the middleware source is injected per
15+
# context. Locally we never touch the committed file: we copy it to a gitignored composer.run.json
16+
# and inject path repos to the sibling working copies (../http-wsse-middleware,
17+
# ../psr18-attachments-middleware), which are checked out on their feature branches and carry the
18+
# new code. Run composer against that copy via COMPOSER=composer.run.json.
19+
#
20+
# Post-merge (both feature branches on main, new code on Packagist): the sibling repos are no longer
21+
# needed, and this whole dance can collapse to a plain `composer install --no-interaction`.
22+
RUN_PHP = cp composer.json composer.run.json && \
23+
COMPOSER=composer.run.json composer config repositories.wsse path ../http-wsse-middleware && \
24+
COMPOSER=composer.run.json composer config repositories.attachments path ../psr18-attachments-middleware && \
25+
COMPOSER=composer.run.json composer update --no-interaction && \
26+
vendor/bin/phpunit $(SUITE_ARG)
27+
1428
.PHONY: help jar certs images up down test interop clean
1529

1630
help:
@@ -42,17 +56,15 @@ down:
4256
docker compose down -v
4357

4458
test:
45-
docker compose run --rm php sh -lc \
46-
"composer install --no-interaction && vendor/bin/phpunit $(SUITE_ARG)"
59+
docker compose run --rm php sh -lc "$(RUN_PHP)"
4760

4861
# The one-liner a user runs. Order: jar -> images -> certs -> up -> test, always tearing down at the
4962
# end (even on test failure) so no containers/volumes are left behind.
5063
interop: jar images certs
5164
@set -e; \
5265
docker compose up -d --wait oracle; \
5366
status=0; \
54-
docker compose run --rm php sh -lc \
55-
"composer install --no-interaction && vendor/bin/phpunit $(SUITE_ARG)" || status=$$?; \
67+
docker compose run --rm php sh -lc "$(RUN_PHP)" || status=$$?; \
5668
docker compose down -v; \
5769
exit $$status
5870

0 commit comments

Comments
 (0)