Skip to content

Commit cc8c779

Browse files
committed
feat: Add GitHub workflow for integration tests on multiple Java versions
1 parent fffc440 commit cc8c779

3 files changed

Lines changed: 178 additions & 0 deletions

File tree

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/usr/bin/env bash
2+
# Prints the newest capi-release version whose CC API (v2) version equals SUPPORTED_API_VERSION
3+
# from CloudFoundryClient.java. Needs only git and curl, no GitHub API and so no token.
4+
#
5+
# A capi-release tag pins cloud_controller_ng as a submodule, and that repo records its v2 API
6+
# version in config/version_v2. The release notes aren't reliable for this. The v2 version only
7+
# grows with the tags, so a binary search over the sorted tags is enough.
8+
set -euo pipefail
9+
10+
source_file="$(dirname "$0")/../../cloudfoundry-client/src/main/java/org/cloudfoundry/client/CloudFoundryClient.java"
11+
target="$(sed -n 's/.*String SUPPORTED_API_VERSION = "\([0-9.]*\)";.*/\1/p' "$source_file")"
12+
[ -n "$target" ] || { echo "SUPPORTED_API_VERSION not found in $source_file" >&2; exit 1; }
13+
14+
workdir="$(mktemp -d)"
15+
trap 'rm -rf "$workdir"' EXIT
16+
# commits and trees only, which is all it takes to read the submodule commit of a tag
17+
git clone --quiet --bare --filter=blob:none https://github.com/cloudfoundry/capi-release.git "$workdir/capi-release"
18+
19+
mapfile -t tags < <(git -C "$workdir/capi-release" tag -l | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | sort -V)
20+
21+
v2_version() {
22+
local sha
23+
sha="$(git -C "$workdir/capi-release" ls-tree "$1" src/cloud_controller_ng | awk '{print $3}')"
24+
curl -fsSL --retry 3 "https://raw.githubusercontent.com/cloudfoundry/cloud_controller_ng/$sha/config/version_v2" | tr -d '[:space:]'
25+
}
26+
27+
# highest index whose v2 version is <= target
28+
lo=0
29+
hi=$((${#tags[@]} - 1))
30+
found=-1
31+
while [ "$lo" -le "$hi" ]; do
32+
mid=$(((lo + hi) / 2))
33+
v="$(v2_version "${tags[$mid]}")"
34+
if [ "$(printf '%s\n%s\n' "$v" "$target" | sort -V | tail -1)" = "$target" ]; then
35+
found=$mid
36+
lo=$((mid + 1))
37+
else
38+
hi=$((mid - 1))
39+
fi
40+
done
41+
42+
if [ "$found" -lt 0 ] || [ "$(v2_version "${tags[$found]}")" != "$target" ]; then
43+
echo "No capi-release found for CC API version $target" >&2
44+
exit 1
45+
fi
46+
47+
echo "CC API $target -> capi-release ${tags[$found]}" >&2
48+
echo "${tags[$found]}"

‎.github/workflows/ci-java.yml‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,9 @@ jobs:
4141
name: Check style with Spotless
4242
run: ./mvnw spotless:check -Pintegration-test
4343

44+
integration-test:
45+
needs: build
46+
uses: ./.github/workflows/integration-test.yml
47+
with:
48+
java-versions: '[21]'
49+
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
name: Integration Tests
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
java-versions:
7+
description: 'JSON array of Java versions to test'
8+
type: string
9+
required: false
10+
default: '[8, 11, 17, 21]'
11+
preview:
12+
description: 'Deploy the latest cf-deployment versions instead of the default ones'
13+
type: boolean
14+
required: false
15+
default: false
16+
schedule:
17+
# preview run: latest versions (including CAPI) on the latest JDK only
18+
- cron: '0 3 * * 1-5'
19+
workflow_call:
20+
inputs:
21+
java-versions:
22+
description: 'JSON array of Java versions to test'
23+
type: string
24+
required: false
25+
default: '[8, 11, 17, 21]'
26+
preview:
27+
description: 'Deploy the latest cf-deployment versions instead of the default ones'
28+
type: boolean
29+
required: false
30+
default: false
31+
32+
permissions:
33+
contents: read
34+
35+
# A new push supersedes the running test. The group name differs from the caller's workflow name on
36+
# purpose: a called workflow shares github.workflow with its caller, which would cancel the caller.
37+
concurrency:
38+
group: integration-test-${{ github.event_name == 'schedule' && 'schedule' || github.ref }}
39+
cancel-in-progress: true
40+
41+
env:
42+
CF_API_HOST: api.cf.127-0-0-1.nip.io
43+
CF_UAA_HOST: uaa.cf.127-0-0-1.nip.io
44+
45+
jobs:
46+
integration-test:
47+
# the cron trigger also fires on forks, where nobody wants a nightly KinD run
48+
if: ${{ github.event_name != 'schedule' || github.repository == 'cloudfoundry/cf-java-client' }}
49+
runs-on: ubuntu-latest
50+
timeout-minutes: 120
51+
strategy:
52+
fail-fast: false
53+
matrix:
54+
java: ${{ fromJSON(inputs.java-versions || (github.event_name == 'schedule' && '[21]' || '[8, 11, 17, 21]')) }}
55+
name: Java ${{ matrix.java }} integration test${{ (inputs.preview || github.event_name == 'schedule') && ' (preview)' || '' }}
56+
steps:
57+
- uses: actions/checkout@v7
58+
with:
59+
submodules: recursive
60+
# Validation runs deploy the capi-release that matches SUPPORTED_API_VERSION. Preview runs
61+
# (scheduled, or started by hand with `preview`) keep the latest versions.
62+
- name: Resolve CAPI version
63+
id: capi
64+
if: ${{ !(inputs.preview || github.event_name == 'schedule') }}
65+
run: |
66+
# separate assignment, so that a failing resolver fails the step
67+
version="$(.github/scripts/resolve-capi-version.sh)"
68+
echo "version=$version" >> "$GITHUB_OUTPUT"
69+
# Overrides the capi chart version of kind-deployment (merged last by Helmfile).
70+
# kind-deployment's helmfile passes cloudController.appDomains, which the capi chart only
71+
# accepts from 1.241.0 on (1.240.0 fails its values schema), so older matches are raised to it.
72+
- name: Write CAPI values override
73+
id: values
74+
if: ${{ steps.capi.outputs.version != '' }}
75+
env:
76+
MIN_CAPI_VERSION: 1.241.0
77+
MATCHED_CAPI_VERSION: ${{ steps.capi.outputs.version }}
78+
run: |
79+
version="$(printf '%s\n%s\n' "$MIN_CAPI_VERSION" "$MATCHED_CAPI_VERSION" | sort -V | tail -1)"
80+
if [ "$version" != "$MATCHED_CAPI_VERSION" ]; then
81+
echo "::warning::capi-release $MATCHED_CAPI_VERSION matches SUPPORTED_API_VERSION but is too old for kind-deployment, deploying $version"
82+
fi
83+
cat > "$RUNNER_TEMP/capi-values.yaml" <<EOF
84+
charts:
85+
capi:
86+
version: $version
87+
EOF
88+
echo "file=$RUNNER_TEMP/capi-values.yaml" >> "$GITHUB_OUTPUT"
89+
# Every job gets its own Cloud Foundry on KinD, so the matrix can run in parallel.
90+
# The action deploys the kind-deployment ref given in `ref`, so keep both on the same commit.
91+
# TEMPORARY: the fork contains cloudfoundry/kind-deployment#516 (postgres-max-connections).
92+
- name: Set up Cloud Foundry
93+
uses: ZPascal/kind-deployment/.github/actions/setup-cf@4d1dc903ddd9438bc46f0830f96295c0f4544648
94+
with:
95+
ref: 0ed311315c9852fef89690cf0174a760dbb1e5b9
96+
use-latest-versions: ${{ (inputs.preview || github.event_name == 'schedule') }}
97+
github-token: ${{ github.token }}
98+
# all components share one Postgres, which runs out of its default 100 connections
99+
postgres-max-connections: '500'
100+
additional-values-files: ${{ steps.values.outputs.file }}
101+
- name: Set up Java
102+
uses: actions/setup-java@v5
103+
with:
104+
distribution: liberica
105+
java-version: ${{ matrix.java }}
106+
- name: Cache Maven packages
107+
uses: actions/cache@v6
108+
with:
109+
path: ~/.m2
110+
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
111+
restore-keys: ${{ runner.os }}-m2
112+
- name: Run integration tests
113+
# CC_ADMIN_PASSWORD and UAA_ADMIN_SECRET are exported by setup-cf
114+
env:
115+
TEST_APIHOST: ${{ env.CF_API_HOST }}
116+
TEST_ADMIN_USERNAME: ccadmin
117+
TEST_ADMIN_PASSWORD: ${{ env.CC_ADMIN_PASSWORD }}
118+
TEST_ADMIN_CLIENTID: admin
119+
TEST_ADMIN_CLIENTSECRET: ${{ env.UAA_ADMIN_SECRET }}
120+
TEST_SKIPSSLVALIDATION: 'true'
121+
TEST_QUOTAS_ROUTES_RESERVEDPORTS: '50'
122+
# kind-deployment has no metric registrar, which the log-cache metric tests need
123+
TEST_SKIP_METRIC_REGISTRAR: 'true'
124+
run: ./mvnw -B -Pintegration-test test -Dgpg.skip

0 commit comments

Comments
 (0)