ci(ric): run smoke and OS integration tests on CodeBuild runners by darklight3it · Pull Request #666 · aws/aws-lambda-java-libs · GitHub
Skip to content

ci(ric): run smoke and OS integration tests on CodeBuild runners - #666

Open
darklight3it wants to merge 14 commits into
mainfrom
ci/ric-integ-on-codebuild-runners
Open

darklight3it wants to merge 14 commits into
mainfrom
ci/ric-integ-on-codebuild-runners

Conversation

@darklight3it

@darklight3it darklight3it commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

Issue #, if available:

Description of changes:

Draft: do not merge yet. The jobs run on CodeBuild runners whose network allowlist update is not deployed yet. See Before merging.

Problem

The RIC PR checks keep failing with 429 / Data limit exceeded from public.ecr.aws.

  • Anonymous pulls from public.ecr.aws are limited to 500 GB of data per month per source IP. GitHub-hosted runners share IPs with other tenants, so the limit is often used up before our jobs start.
  • The smoke and integration jobs ran each buildspec through CodeBuild local. Every shard pulled the 1.3 GB codebuild/local-builds agent image (about 80% of our bytes), then the base images for the JNI build and the function images.
  • ci(ric): Cut the number of pulls from AWS public ECR #663 reduced the number of pulls and how many run at once, but cannot fix the per-IP limit.

Approach

Run the jobs that build and run containers on the existing release CodeBuild runners (codebuild-aws-lambda-java-libs-test-trigger-<x86|arm64>), the same ones release-runtime-interface-client.yml uses. Base images come through an ECR pull-through cache, and CodeBuild local is no longer needed.

The release runners are in an egress-locked network, so the jobs do what the release jobs do:

  • the JDK is the runner image's preinstalled Corretto 8 (actions/setup-java can't download one there);
  • Maven resolves through the CodeArtifact Maven Central proxy (configure-maven-mirror).

The tests themselves are the same OS / distro version / runtime / platform combinations.

Changes

One test script instead of CodeBuild local

  • New test/integration/codebuild/scripts/run_os_test.sh runs one combination on the host. It builds the RIC and the test handler (without unit tests, which the build check runs), builds the function image with the Runtime Interface Emulator, invokes it and checks the response, then collects container logs and cleans up. It replaces run_invocation_test.sh, fetch_test_container_logs.sh and clean_up.sh. Container names include the OS, version and runtime, so different combinations can run side by side.
  • Each Dockerfile.function.* is now the full test image: it installs curl (used by the tester container) and unpacks the Runtime Interface Emulator itself, instead of the script appending both to a temporary copy.
  • The per-OS buildspecs now call this script. Their batch matrices are unchanged.
  • Deleted test/integration/codebuild-local/. docker-retry.sh moved to codebuild/scripts/.

Matrix

  • The integration matrix is defined in the workflow: 9 OS / version / runtime targets × 2 platforms, minus Amazon Linux 1 on arm64, so 17 jobs.
  • The smoke tests are folded into it: alpine 3.15 was already in it, so only amazoncorretto 11 is added.

Workflow (runtime-interface-client_pr.yml)

  • integration-test-matrix runs on the release runners, every platform on a native host. The smoke-test-arch and smoke-test jobs are removed.
  • New composite action .github/actions/use-runner-corretto8 sets up the image's Corretto 8 and the JDK 8 Maven toolchain.
  • Each job logs in to ECR with the runner's own account and region (no repository secrets, which fork PRs don't get) and sets BASE_REGISTRY. The JNI build already reads it, and the function Dockerfiles now take it as a build arg too, defaulting to public.ecr.aws.
  • max-parallel: 8 on the integration matrix, to stay inside the CodeBuild concurrency quota.
  • The integration-test and build check names are unchanged. smoke-test no longer exists, so it must be removed from the required checks.

Fork PRs

  • Fork PRs run the integration tests like any other PR, after a maintainer reviews the change and approves the workflow run. That approval is the gate, since the runners run in our AWS account.

Local runs

  • make test-integ OS_DISTRIBUTION=debian DISTRO_VERSION=bookworm RUNTIME_VERSION=corretto11 PLATFORM=linux/amd64 runs one combination.
  • A platform other than the host's needs emulation: Docker Desktop has it built in; on Linux, register qemu once (the command is in the Makefile).
  • The RIC README has a new OS Integration Tests section with the local setup (JDK 8 toolchain, emulation on macOS, Windows and Linux).
  • make pr runs the unit tests. The test-smoke-* and pr-<arch> targets are removed.

JNI build base images

  • Every Maven build of the RIC builds the JNI library in Docker from amazonlinux:2 and alpine:3, so build, dockerized-test and the coverage jobs on main pulled them anonymously on every run, and failed the same way.
  • New composite action .github/actions/cache-jni-base-images loads both images into the local Docker image store from the Actions cache, pulling only on a weekly cache miss. Those jobs use the buildx docker driver, which builds from the local store. Works in forks too, with no AWS access.

Fixes (carried over into run_os_test.sh)

  • A failed invocation printed "unbound variable" instead of the expected and actual output (the old script referenced an unset ${RUNTIME} under set -u).
  • Emulated runs only got the long invocation timeout on aarch64 hosts, so emulated tests on macOS (where arch prints arm64 or i386) or on x86_64 hosts timed out after 10 s. It now applies to any platform that isn't the host's.

Coverage and savings

No test coverage is removed.

Before After
OS / version / runtime / platform combinations tested 17 17 (same set)
Test executions 19 (15 integration + 4 smoke; alpine 3.15 ran in both) 17
RIC unit tests in build, and again inside every integration shard in build only
Codecov upload build build (unchanged)

Anonymous public.ecr.aws pulls per PR (counted as in #663, one per docker build or docker pull)

Job Before After
integration 111 0 (through the ECR pull-through cache)
smoke 28 0 (folded into integration)
build (2 archs) 16 0 on a cache hit; 4 on the weekly cache miss
Total 155 0 most PRs

That also drops the 1.3 GB codebuild/local-builds agent image every integration and smoke job pulled, about 17 GB per PR across 13 jobs. dockerized-test still pulls lambda/java:25 once (see Not in this PR).

Time, measured on this repo's runs:

Before (run 39405594958) After (run 39609575071)
Integration / smoke job 6.0–10.3 min 3.1–4.0 min
build job 4.6–5.4 min 3.7–4.3 min
Total job time ~113 min ~67 min
Wall clock ~25 min (max-parallel: 4) ~22 min (max-parallel: 8)

The "after" integration times include the full RIC build. Before: the wall clock is attempt 1 of that run (alpine 3.15 and debian x64 failed with 429 and were re-run); job times and total are from the final, green jobs. After: most of the ~22 min was spent waiting for CodeBuild runners. All 17 matrix jobs were queued at the start, but the first one got a runner only after ~8 min, and the others were picked up one at a time over the next ~7.5 min. In attempt 1 of the same run (which failed on the network allowlist), runners picked up the jobs within a minute and the whole run took ~10 min.

Before merging

  1. Deploy the runner network allowlist update for the distro package mirrors the test images install from (in progress).
  2. Set Settings → Actions → General → Fork pull request workflows → Require approval for all external contributors.
  3. Remove smoke-test from the required status checks.
  4. Run this PR end to end on the runners.

Not in this PR

  • The per-OS buildspecs (test/integration/codebuild/buildspec.os.*.yml) stay for now: the PR workflow no longer uses them, but they still define their own batch matrix for other CodeBuild-based CI. A follow-up PR removes them, along with configure_multi_arch_env.sh, once nothing else runs them. Until then, the matrix in the workflow is the one the PR checks use.
  • dockerized-test still pulls lambda/java:25 anonymously for its test image.
  • The failing publish job on main is removed separately in ci(ric): remove dead snapshot publish job from merge-to-main #665.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

The RIC smoke and OS integration tests ran their buildspecs through
CodeBuild local on GitHub-hosted runners. Every shard pulled the 1.3 GB
codebuild/local-builds image plus all base images anonymously from
public.ecr.aws, and GitHub runner IPs are shared with other tenants, so
the checks kept failing on its anonymous data limit.

- Replace CodeBuild local with run_os_test.sh, one script that runs one
  OS / distro version / runtime / platform test directly on the host.
  The per-OS buildspecs, the Makefile targets and CI all call it, so the
  same tests run locally again (`make test-integ`, `make test-smoke-<arch>`).
- Move the CI matrix to test/integration/os-test-matrix.json, shared by
  the workflow and `make test-integ` (run_all_os_tests.sh).
- Run the smoke and integration jobs on CodeBuild-hosted runners and pull
  base images (function images and the JNI build) through an ECR
  pull-through cache via BASE_REGISTRY.
- Skip these jobs on fork PRs, since the runners run in our AWS account;
  their checks pass with a notice and a maintainer runs the tests from a
  branch in this repository before merging.
- Install a qemu emulator only when a platform differs from the host, and
  use the long invocation timeout for any emulated platform.
- Fix run_invocation_test.sh referencing the unset RUNTIME variable.
@codecov

codecov Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 66.66%. Comparing base (039d373) to head (04350fb).

Additional details and impacted files
@@            Coverage Diff            @@
##               main     #666   +/-   ##
=========================================
  Coverage     66.66%   66.66%           
  Complexity      223      223           
=========================================
  Files            35       35           
  Lines          1020     1020           
  Branches        146      146           
=========================================
  Hits            680      680           
  Misses          288      288           
  Partials         52       52           
Flag Coverage Δ
aarch64 66.66% <ø> (ø)
x86_64 66.27% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Run the smoke and integration jobs on the existing release CodeBuild
runners (aws-lambda-java-libs-test-trigger-<arch>) instead of dedicated
ones. Those runners are egress-locked, so do what the release jobs do:
use the image's preinstalled Corretto 8 (new use-runner-corretto8
action) instead of actions/setup-java, and resolve Maven through the
CodeArtifact proxy (configure-maven-mirror). Only the distro package
mirrors the test images install from still need egress.
Keep comments to current behaviour; the rationale is in the PR
description.
- Fold the smoke tests into the integration matrix: alpine 3.15 was
  already in it, so only amazoncorretto 11 is added. Removes the
  smoke-test jobs and the test-smoke / pr-<arch> make targets.
- Stop skipping fork PRs. Fork workflows already need maintainer
  approval to run, which is the actual gate.
- Run local integration tests for the host's platform only, which
  removes the qemu setup from run_os_test.sh.
The JSON matrix only existed so make test-integ could run every
combination locally, and local runs are now one combination at a time.
Inline the matrix and drop os-test-matrix.json, the load job and
run_all_os_tests.sh.
… macOS

run_invocation_test.sh only gave emulated runs the long timeout on
aarch64 hosts, so emulated tests on macOS (where arch prints arm64 or
i386) or on x86_64 hosts used the 10s timeout. Use it for any platform
that isn't the host's.
The JNI build pulls amazonlinux:2 and alpine:3 from public.ecr.aws on
every Maven build, so the build, coverage and dockerized-test jobs kept
failing on the anonymous data limit shared by GitHub runner IPs. Load
the images from the Actions cache into the local image store (pulling
only on a weekly cache miss) and use the buildx docker driver, which
builds from the local store.
run_os_test.sh copied each Dockerfile.function.* into .scratch and
appended the curl install and the RIE COPY. Do both in the Dockerfiles
(ADD unpacks the RIE archive, RIE is a build arg), so each Dockerfile is
the full image definition and the script builds it directly.
- Log in to the ECR pull-through cache with the runner's account and
  region instead of repository secrets, which fork PRs don't get.
- Skip unit tests when building in run_os_test.sh; the build job runs
  them.
- Don't retry the function image build; pulls go through the cache, and
  a broken Dockerfile should fail fast.
- Fold run_invocation_test.sh, fetch_test_container_logs.sh and
  clean_up.sh into run_os_test.sh, with container and network names per
  OS / version / runtime so local runs don't collide.
- Start the function with `java` from the image's PATH, dropping
  JAVA_BINARY_LOCATION.
- cache-jni-base-images: pull when the cached tar can't be loaded.
- dockerized-test: also run when cache-jni-base-images changes.
RIE doesn't look the bootstrap up on PATH, so resolve it in the
container's shell.
Every ARG used in FROM needs a default, otherwise BuildKit warns
InvalidDefaultArgInFrom. run_os_test.sh always passes them.
@darklight3it
darklight3it marked this pull request as ready for review October 21, 2026 13:36

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants