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
1 change: 1 addition & 0 deletions .envoy-version
Copy link
Member Author

@mathetake mathetake Oct 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: This file is what func-e honors as you can see in the help message by go tool -modfile=tools/go.mod func-e help run

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.36.2
28 changes: 4 additions & 24 deletions .github/workflows/build_and_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -136,20 +136,13 @@ jobs:
test_extproc:
needs: changes
if: ${{ needs.changes.outputs.code == 'true' }}
name: External Processor Test (Envoy v${{ matrix.version }} on ${{ matrix.os }})
name: External Processor Test (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
# Note: we cannot run the latest Envoy version on macOS due to https://github.com/tetratelabs/archive-envoy/issues/12.
# Once it's supported, the following "binary installation" steps below can be just removed and
# we can simply exec.Cmd with "go tool -modfile=tools/go.mod func-e run" with the envoy version configured via ENVOY_VERSION env var.
Comment on lines -143 to -145
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we no longer need to test on Envoy latest, which made this PR possible

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also i realized that latest installation had been broken since one-two months ago due to the upstream repo change, so it was useless anyways

include:
- version: 1.35.0 # NOTE: when updating this, also update the comment in the CONTRIBUTING.md file.
os: ubuntu-latest
- version: 1.35.0 # NOTE: when updating this, also update the comment in the CONTRIBUTING.md file.
os: macos-latest
- version: latest
os: ubuntu-latest
os:
- ubuntu-latest
- macos-latest
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
Expand All @@ -164,19 +157,6 @@ jobs:
~/go/pkg/mod
~/go/bin
key: extproc-tests-${{ hashFiles('**/go.mod', '**/go.sum', '**/Makefile') }}
- name: Install stable Envoy via func-e
if: matrix.version != 'latest'
run: |
go tool -modfile=tools/go.mod func-e use ${{ matrix.version }}
echo $HOME/.func-e/versions/${{ matrix.version }}/bin >> $GITHUB_PATH
- name: Install latest Envoy
if: matrix.version == 'latest'
run: |
export ENVOY_BIN_DIR=$HOME/envoy/bin
mkdir -p $ENVOY_BIN_DIR
docker run -v $ENVOY_BIN_DIR:/tmp/ci -w /tmp/ci \
--entrypoint /bin/cp envoyproxy/envoy-dev:latest /usr/local/bin/envoy .
echo $ENVOY_BIN_DIR >> $GITHUB_PATH
- env:
TEST_AWS_ACCESS_KEY_ID: ${{ secrets.AWS_BEDROCK_USER_AWS_ACCESS_KEY_ID }}
TEST_AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_BEDROCK_USER_AWS_SECRET_ACCESS_KEY }}
Expand Down
6 changes: 0 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,6 @@ For example,

- The latest `kubectl` binary for running `make test-e2e`.
- See: https://kubernetes.io/docs/tasks/tools/
- The latest `envoy` binary for running `make test-extproc`. The current required version is v1.35 or later.
- On Linux, you can download the latest Envoy binary as described in https://www.envoyproxy.io/docs/envoy/latest/start/install.
Alternatively, you can use `func-e` on Linux as well like on macOS below.
- On macOS, since `brew envoy` tends to behind the latest version, it is recommended use `func-e` to run the latest Envoy. See https://func-e.io/.
- `alias envoy='func-e run'` is a convenient way to run the latest Envoy binary via `func-e` on both macOS and Linux.
For example, `func-e use 1.34` can be used to switch to a specific version of Envoy to be run with `func-e run`.

Other than that, everything will be automatically managed and installed via `make` targets,
and you should not need to worry about the dependencies (tell us if you do).
Expand Down
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ test-crdcel: apigen ## Run the integration tests of CEL validation in CRD defini
.PHONY: test-extproc # This requires the extproc binary to be built.
test-extproc: build.extproc ## Run the integration tests for extproc without controller or k8s at all.
@$(MAKE) build.testupstream CMD_PATH_PREFIX=tests/internal/testupstreamlib
@echo "Ensure func-e is built and Envoy is installed"
@@$(GO_TOOL) func-e run --version >/dev/null 2>&1
@echo "Run ExtProc test"
@EXTPROC_BIN=$(OUTPUT_DIR)/extproc-$(shell go env GOOS)-$(shell go env GOARCH) go test ./tests/extproc/... $(GO_TEST_E2E_ARGS)

Expand Down
4 changes: 1 addition & 3 deletions tests/extproc/extproc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,7 @@ var (
Region: "gcp-region",
ProjectName: "gcp-project-name",
}}}
// This always failing backend is configured to have AWS Bedrock schema so that
// we can test that the extproc can fallback to the different schema. E.g. Primary AWS and then OpenAI.
alwaysFailingBackend = filterapi.Backend{Name: "always-failing-backend", Schema: awsBedrockSchema}
alwaysFailingBackend = filterapi.Backend{Name: "always-failing-backend", Schema: openAISchema}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very hard to explain but this was accidentally working until v1.36 which makes it possible for extproc return the immediate response correctly, so this makes the embedding endpoint test not working: AWS schema doesn't have support for embedding -> try returning immediate response -> previously it was retry-able (due to timeout) vs not retry-able due to extpric immediate response.

In practice, this schema diff retry test case is already covered in the e2e test so no harm


// envoyConfig is the embedded Envoy configuration template.
//
Expand Down
32 changes: 31 additions & 1 deletion tests/internal/testenvironment/test_environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"net"
"os"
"os/exec"
"path/filepath"
"runtime"
"strconv"
"strings"
Expand All @@ -24,6 +25,7 @@ import (

"github.com/envoyproxy/ai-gateway/cmd/extproc/mainlib"
internaltesting "github.com/envoyproxy/ai-gateway/internal/testing"
testsinternal "github.com/envoyproxy/ai-gateway/tests/internal"
)

// TestEnvironment holds all the services needed for tests.
Expand Down Expand Up @@ -257,14 +259,42 @@ func requireEnvoy(t testing.TB,
envoyYamlPath := t.TempDir() + "/envoy.yaml"
require.NoError(t, os.WriteFile(envoyYamlPath, []byte(processedConfig), 0o600))

cmd := exec.CommandContext(t.Context(), "envoy",
// Note: do not pass t.Context() to CommandContext, as it's canceled
// *before* t.Cleanup functions are called.
//
// > Context returns a context that is canceled just before
// > Cleanup-registered functions are called.
//
// That means the subprocess gets killed before we can send it an interrupt
// signal for graceful shutdown, which results in orphaned subprocesses.
ctx, cancel := context.WithCancel(context.Background())
cmd := testsinternal.GoToolCmdContext(ctx, "func-e", "run",
"-c", envoyYamlPath,
"--concurrency", strconv.Itoa(max(runtime.NumCPU(), 2)),
// This allows multiple Envoy instances to run in parallel.
"--base-id", strconv.Itoa(time.Now().Nanosecond()),
// Add debug logging for http.
"--component-log-level", "http:debug",
)
// func-e will use the version specified in the project root's .envoy-version file.
cmd.Dir = internaltesting.FindProjectRoot()
version, err := os.ReadFile(filepath.Join(cmd.Dir, ".envoy-version"))
require.NoError(t, err)
t.Logf("Starting Envoy version %s", strings.TrimSpace(string(version)))
cmd.WaitDelay = 3 * time.Second // auto-kill after 3 seconds.
t.Cleanup(func() {
defer cancel()
// Graceful shutdown, should kill the Envoy subprocess, too.
if err := cmd.Process.Signal(os.Interrupt); err != nil {
t.Logf("Failed to send interrupt to aigw process: %v", err)
}
// Wait for the process to exit gracefully, in worst case this is
// killed in 3 seconds by WaitDelay above. In that case, you may
// have a zombie Envoy process left behind!
if _, err := cmd.Process.Wait(); err != nil {
t.Logf("Failed to wait for aigw process to exit: %v", err)
}
})

// wait for the ready message or exit.
StartAndAwaitReady(t, cmd, stdout, stderr, "starting main dispatch loop")
Expand Down
Loading