Skip to content

Commit e1575ba

Browse files
committed
ci: Test upper bound dependenices file in Github CI
1 parent c34e384 commit e1575ba

File tree

3 files changed

+215
-0
lines changed

3 files changed

+215
-0
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#!/bin/bash
2+
3+
# This script generates a maven command to test unit and integration tests for
4+
# the repo. The outputted maven command will be in the rough following format
5+
# `mvn verify ... -D{dependency.name}.version={dependency.version]`. The variables
6+
# ${dependency.name} and ${dependency.version} are parsed from the input to the script.
7+
#
8+
# Default invocation ./.github/scripts/test_dependency_compatibility.sh will use the default
9+
# upper-bounds dependency file at the root of the repo.
10+
# There are two potential inputs to the script:
11+
# 1. -f {file}: Custom file/path for the upper-bound dependencies to test
12+
# 2. -l {deps_list}: Comma-separated list of dependencies to test (e.g. protobuf=4.31.0,guava=33.4.8-jre)
13+
# Note: Do not include the `-D` prefix or `.version` suffix. Those values will be appended when generating
14+
# the maven command.
15+
#
16+
# If both inputs are supplied, the deps_list input has precedence. For Github Actions workflow,
17+
# the default workflow will run with the upper-bounds file. A `workflow_dispatch` option takes in
18+
# an input for the deps_list to manually run a subset of dependencies.
19+
#
20+
# The default upper-bound dependencies file is `dependencies.txt` located in the root
21+
# of sdk-platform-java. The upper-bound dependencies file will be in the format of:
22+
# ${dependency.name}=${dependency.version}
23+
24+
set -ex
25+
26+
function print_help() {
27+
echo "Unexpected input argument for this script."
28+
echo "Use -f {file} for the directory of the upper-bound dependencies file."
29+
echo "Use -l {deps_list} for a comma-separated list of dependencies to test (Format: dep1=1.0,dep2=2.0)"
30+
}
31+
32+
# Function to parse a dependency string and append it to the Maven command
33+
function add_dependency_to_maven_command() {
34+
local dep_pair=$1
35+
if [[ ! "${dep_pair}" =~ .*=.* ]]; then
36+
echo "Malformed dependency string: ${dep_pair}. Expected format: dependency=version"
37+
exit 1
38+
fi
39+
local dependency=$(echo "${dep_pair}" | cut -d'=' -f1 | tr -d '[:space:]')
40+
local version=$(echo "${dep_pair}" | cut -d'=' -f2 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
41+
MAVEN_COMMAND+=" -D${dependency}.version=${version}"
42+
}
43+
44+
# Default to the upper bounds file in the root of the repo
45+
file='dependencies.txt'
46+
dependency_list=''
47+
48+
# The colon (:) after the letter means that there is an input associated with the flag
49+
while getopts 'f:l:' flag; do
50+
case "${flag}" in
51+
f) file="${OPTARG}" ;;
52+
l) dependency_list="${OPTARG}" ;;
53+
*) print_help && exit 1
54+
esac
55+
done
56+
57+
# Error if both the file and deps_list inputs is empty
58+
if [[ -z "${file}" && -z "${dependency_list}" ]]; then
59+
print_help && exit 1
60+
fi
61+
62+
MAVEN_COMMAND="mvn verify -Penable-integration-tests -Dclirr.skip -Dcheckstyle.skip -Dfmt.skip -Denforcer.skip "
63+
64+
# Check if a list of dependencies was provided as an argument. If the list of dependency inputted
65+
# is empty, then run with the upper-bound dependencies file
66+
if [ -z "${dependency_list}" ]; then
67+
UPPER_BOUND_DEPENDENCY_FILE=$file
68+
69+
if [ ! -e "${UPPER_BOUND_DEPENDENCY_FILE}" ]; then
70+
echo "The inputted upper-bound dependency file '${UPPER_BOUND_DEPENDENCY_FILE}' cannot be found"
71+
exit 1
72+
fi
73+
74+
# Read the file line by line
75+
while IFS= read -r line; do
76+
# Ignore any comments and blank lines
77+
if [[ "${line}" =~ ^[[:space:]]*# ]] || [[ -z "${line}" ]]; then
78+
continue
79+
fi
80+
add_dependency_to_maven_command "${line}"
81+
done < "${UPPER_BOUND_DEPENDENCY_FILE}"
82+
else # This else block means that a list of dependencies was inputted
83+
# Set the Internal Field Separator (IFS) to a comma.
84+
# This tells 'read' to split the string by commas into an array named DEPS.
85+
# The 'read -ra' command reads the input into an array.
86+
IFS=',' read -ra DEPS <<< "${dependency_list}"
87+
88+
# Loop through each item in the DEPS array.
89+
for DEP_PAIR in "${DEPS[@]}"; do
90+
# Skip any empty items that might result from trailing commas.
91+
if [ -z "${DEP_PAIR}" ]; then
92+
continue
93+
fi
94+
add_dependency_to_maven_command "${DEP_PAIR}"
95+
done
96+
fi
97+
98+
# Run the generated maven command to test with the dependency versions
99+
$MAVEN_COMMAND
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: Dependency Compatibility Test
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- 'main'
7+
workflow_dispatch:
8+
inputs:
9+
dependencies-list:
10+
description: 'Comma-separated list of dependencies to test (Example format: protobuf=4.31.0,guava=33.4.8-jre).
11+
Do not include the `-D` prefix or `.version` suffix. Those values will be appended when generating
12+
the command. No input (default) will run the the upper-bound dependencies file.'
13+
required: false
14+
default: ''
15+
16+
jobs:
17+
dependency-compatibility-test:
18+
runs-on: ubuntu-latest
19+
permissions:
20+
contents: read
21+
steps:
22+
- name: Checkout sdk-platform-java
23+
uses: actions/checkout@v4
24+
- name: Set up JDK 21
25+
uses: actions/setup-java@v4
26+
with:
27+
java-version: '21'
28+
distribution: 'temurin'
29+
cache: maven
30+
# The workflow_dispatch event is for team members who want to manually test certain dependencies + version combos
31+
# The normal workflow is not from `workflow_dispatch` and will use the default upper-bounds dependencies file
32+
- name: Determine Inputted Dependencies List
33+
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.dependencies-list != '' }}
34+
run: echo "DEPENDENCIES_LIST=${{ github.event.inputs.dependencies-list }}" >> $GITHUB_ENV
35+
# Install the modules for the rest of the CI
36+
- name: Install sdk-platform-java's modules
37+
# gapic-generator-java requires Java 8 and is irrelevant for this CI
38+
run: mvn -q -B -ntp install --projects '!gapic-generator-java' -Dcheckstyle.skip -Dfmt.skip -DskipTests -Dclirr.skip -T 1C
39+
40+
# Run in the root module which should test for everything except for showcase
41+
- name: Perform Dependency Compatibility Testing
42+
shell: bash
43+
run: |
44+
if [[ -n "${{ env.DEPENDENCIES_LIST }}" ]]; then
45+
./.github/scripts/test_dependency_compatibility.sh -l ${{ env.DEPENDENCIES_LIST }}
46+
else
47+
./.github/scripts/test_dependency_compatibility.sh
48+
fi
49+
# Set up local showcase server to run the showcase ITs
50+
- name: Parse showcase version
51+
working-directory: java-showcase/gapic-showcase
52+
run: echo "SHOWCASE_VERSION=$(mvn help:evaluate -Dexpression=gapic-showcase.version -q -DforceStdout)" >> "$GITHUB_ENV"
53+
- name: Install showcase server
54+
run: |
55+
sudo mkdir -p /usr/src/showcase
56+
sudo chown -R ${USER} /usr/src/
57+
curl --location https://github.com/googleapis/gapic-showcase/releases/download/v${{env.SHOWCASE_VERSION}}/gapic-showcase-${{env.SHOWCASE_VERSION}}-linux-amd64.tar.gz --output /usr/src/showcase/showcase-${{env.SHOWCASE_VERSION}}-linux-amd64.tar.gz
58+
cd /usr/src/showcase/
59+
tar -xf showcase-*
60+
./gapic-showcase run &
61+
cd -
62+
# Run specifically for showcase
63+
- name: Perform Dependency Compatibility Testing (Showcase only)
64+
shell: bash
65+
# Need to cd out of the directory to get the scripts as this step is run inside the java-showcase directory
66+
run: |
67+
if [[ -n "${{ env.DEPENDENCIES_LIST }}" ]]; then
68+
../.github/scripts/test_dependency_compatibility.sh -l ${{ env.DEPENDENCIES_LIST }}
69+
else
70+
../.github/scripts/test_dependency_compatibility.sh -f ../dependencies.txt
71+
fi
72+
working-directory: java-showcase

dependencies.txt

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# This file contains a list of dependencies and their versions to be tested for compatibility.
2+
# The format is key=value, where the key is the dependency name and the value is the version.
3+
# "1P" refers to First-Party dependencies (owned by Google).
4+
# "3P" refers to Third-Party dependencies.
5+
6+
# 1P Parent-Pom
7+
javax.annotation-api=1.3.2
8+
grpc=1.74.0
9+
google.auth=1.37.1
10+
google.http-client=1.47.1
11+
gson=2.13.1
12+
guava=33.4.8-jre
13+
protobuf=4.31.1
14+
opentelemetry=1.52.0
15+
errorprone=4.15.1
16+
j2objc-annotations=3.0.0
17+
threetenbp=1.7.1
18+
slf4j=2.0.17
19+
20+
# 1P Shared-Deps
21+
grpc-gcp=1.6.1
22+
google.oauth-client=1.39.0
23+
google.api-client=2.8.0
24+
25+
# 3P Shared-Deps
26+
threeten-extra=1.8.0
27+
opencensus=0.31.0
28+
findbugs=3.0.2
29+
jackson=2.19.2
30+
errorprone=2.41.0
31+
codec=1.19.0
32+
httpcomponents.httpcore=4.4.16
33+
httpcomponents.httpclient=4.5.14
34+
apache-httpclient-5=5.5
35+
apache-httpcore-5=5.3.4
36+
perfmark-api=0.27.0
37+
j2objc-annotations=3.0.0
38+
google.cloud.opentelemetry=0.36.0
39+
opentelemetry-semconv=1.34.0
40+
flogger=0.9
41+
arrow=18.3.0
42+
dev.cel=0.10.1
43+
com.google.crypto.tink=1.18.0
44+
io.opentelemetry.contrib.opentelemetry-gcp-resources=1.48.0-alpha

0 commit comments

Comments
 (0)