Skip to content

Fix compressed streaming responses at the kernel #368

Fix compressed streaming responses at the kernel

Fix compressed streaming responses at the kernel #368

name: Gateway API Conformance
# Guards that the WSO2 gateway keeps passing the Gateway API conformance suite.
# Triggers:
# - Pull requests that touch kubernetes/** (the operator, helm charts and the
# conformance scripts) or gateway/gateway-controller/** (the xDS / route
# translation conformance most directly exercises) — catches regressions before merge.
# - Manual runs (workflow_dispatch).
# - A weekly schedule (Saturday 00:00 UTC) so drift on main is caught even when no
# triggering change lands. Saturday (not Friday) so the run happens after
# Friday's changes have merged — otherwise a Friday-00:00 run would miss all of
# Friday's work until the following week.
# NOTE: under gateway/, only gateway-controller/** triggers this; the rest of gateway/**
# (e.g. gateway-runtime, policies) does not — add more paths below if you want them to.
on:
workflow_dispatch:
pull_request:
branches:
- main
- gateway/1.2.0-agent-manager
paths:
- 'kubernetes/**'
- 'gateway/gateway-controller/**'
- '.github/workflows/k8s-gateway-api-conformance.yml'
schedule:
# Saturday at 00:00 UTC (cron day-of-week 6 = Saturday) — runs after Friday's
# changes have landed, so each run covers the full week including Friday.
- cron: '0 0 * * 6'
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions:
contents: read
env:
# The conformance scripts derive image tags from gateway/VERSION and the operator
# Makefile, and install-wso2-gateway.sh deploys those exact tags with
# imagePullPolicy=IfNotPresent. So we build with the DEFAULT registry/version (no
# overrides) and let load-images.sh line the tags up automatically.
CONFORMANCE_DIR: kubernetes/conformance
REPORT_OUT: ${{ github.workspace }}/conformance-report.yaml
RUN_LOG: ${{ github.workspace }}/conformance-run.log
jobs:
conformance:
runs-on: ubuntu-24.04
timeout-minutes: 90
outputs:
# passed | failed (ran, some tests failed) | error (died before a report).
# Consumed by the notify job below. Empty if the job died before the publish
# step ran (e.g. an image build failure) — the notify job treats that as an error.
status: ${{ steps.publish.outputs.status }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.26.5'
cache-dependency-path: '**/go.sum'
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: linux/amd64,linux/arm64
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
# docker driver builds straight into the local daemon so `kind load` /
# load-images.sh can see the images.
driver: docker
- name: Set up Helm
uses: azure/setup-helm@v4
- name: Install KinD CLI
# setup-kind.sh requires the kind binary (kubectl, docker, jq, curl are already
# present on ubuntu-24.04). Built via the Go toolchain that's already set up;
# pin the version here if a reproducible kind CLI is desired.
run: go install sigs.k8s.io/kind@latest
# ---- Build the gateway images from source (default tags) -----------------
- name: Build gateway images (controller + runtime)
run: make -C gateway build
- name: Build operator image
run: make -C kubernetes/gateway-operator docker-build
# ---- Stand up the cluster and deploy via the conformance scripts ---------
- name: Create KinD cluster with MetalLB
run: bash "${CONFORMANCE_DIR}/kind/setup-kind.sh"
- name: Load built images into the cluster
run: bash "${CONFORMANCE_DIR}/load-images.sh"
- name: Install cert-manager, operator and GatewayClass
run: bash "${CONFORMANCE_DIR}/install-wso2-gateway.sh"
# ---- Run the suite (never fails the step directly; the outcome is recorded
# and enforced by the reporting step below) --------------------------
- name: Run Gateway API conformance suite
id: run
run: |
set -o pipefail
if bash "${CONFORMANCE_DIR}/run-conformance.sh" 2>&1 | tee "${RUN_LOG}"; then
echo "outcome=passed" >> "$GITHUB_OUTPUT"
else
echo "outcome=failed" >> "$GITHUB_OUTPUT"
fi
# ---- Present the result ---------------------------------------------------
# A report is written by the suite whenever it finishes running (pass OR
# partial fail). If it is missing, the suite died during setup/build/cluster
# bring-up and never reached report generation.
- name: Publish conformance results
id: publish
run: |
if [ -s "${REPORT_OUT}" ]; then
{
echo "## Gateway API Conformance Report"
echo ""
if [ "${{ steps.run.outputs.outcome }}" = "passed" ]; then
echo "**Status: ✅ All conformance tests passed.**"
else
echo "**Status: ❌ Conformance suite completed with failures — full report below.**"
fi
echo ""
echo '```yaml'
cat "${REPORT_OUT}"
echo '```'
} >> "$GITHUB_STEP_SUMMARY"
echo "==================== Gateway API Conformance Report ===================="
cat "${REPORT_OUT}"
echo "======================================================================="
if [ "${{ steps.run.outputs.outcome }}" != "passed" ]; then
echo "status=failed" >> "$GITHUB_OUTPUT"
echo "::error::Gateway API conformance suite reported failures. See the report above."
exit 1
fi
echo "status=passed" >> "$GITHUB_OUTPUT"
echo "Gateway API conformance suite passed."
else
echo "status=error" >> "$GITHUB_OUTPUT"
echo "::error::Conformance suite failed before a report could be generated (setup/build/cluster error)."
{
echo "## Gateway API Conformance — FAILED before report generation"
echo ""
echo "The suite did not produce a report. Tail of the run log:"
echo '```'
tail -n 300 "${RUN_LOG}" 2>/dev/null || echo "(no run log captured)"
echo '```'
} >> "$GITHUB_STEP_SUMMARY"
echo "==================== Conformance run log (tail) ===================="
tail -n 300 "${RUN_LOG}" 2>/dev/null || echo "(no run log captured)"
echo "==================================================================="
exit 1
fi
- name: Upload conformance report and run log
if: always()
uses: actions/upload-artifact@v4
with:
name: gateway-api-conformance-report
path: |
${{ env.REPORT_OUT }}
${{ env.RUN_LOG }}
if-no-files-found: warn
- name: Collect cluster diagnostics on failure
if: failure()
run: |
echo "===== Pods (all namespaces) ====="
kubectl get pods -A -o wide || true
echo "===== Gateways ====="
kubectl get gateways.gateway.networking.k8s.io -A || true
echo "===== HTTPRoutes ====="
kubectl get httproutes.gateway.networking.k8s.io -A || true
echo "===== GatewayClass ====="
kubectl get gatewayclass -A || true
echo "===== Operator logs ====="
kubectl logs -n gateway-system deploy/gateway-operator --tail=200 || true
echo "===== Data-plane pods (conformance infra namespace) ====="
kubectl get pods -n gateway-conformance-infra -o wide || true
# Posts the conformance outcome to the configured Google Chat space — but ONLY for the
# weekly scheduled run. Manual (workflow_dispatch) and pull_request runs are started by
# someone who is already watching the Actions status, so a chat ping would be noise;
# the scheduled run is the unattended monitor, so its result is the one the space needs.
# always() lets it run even when the conformance job failed (a skipped dependency would
# otherwise suppress the very failure we want to hear about).
notify:
name: Notify Google Chat
needs: conformance
if: always() && github.event_name == 'schedule'
runs-on: ubuntu-24.04
steps:
- name: Checkout conformance pin
uses: actions/checkout@v4
with:
sparse-checkout: kubernetes/conformance/runner/go.mod
sparse-checkout-cone-mode: false
# Compares the Gateway API version this suite is pinned to against the latest
# upstream release, so a new release is noticed by the weekly run instead of by
# someone remembering to check kubernetes-sigs/gateway-api by hand.
- name: Check for a newer Gateway API release
id: upstream
env:
# Raises the API rate limit from the shared-IP anonymous quota and needs no
# scope beyond the workflow's top-level `contents: read`.
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -uo pipefail
GOMOD="kubernetes/conformance/runner/go.mod"
# The `require sigs.k8s.io/gateway-api/conformance vX.Y.Z` line is the single
# source of truth for what the suite actually runs (run-conformance.sh resolves
# the suite from the module cache, not from a checkout of the upstream repo).
PINNED=$(grep -oE 'sigs\.k8s\.io/gateway-api/conformance v[0-9]+\.[0-9]+\.[0-9]+' "${GOMOD}" \
| head -n1 | awk '{print $2}')
if [ -z "${PINNED:-}" ]; then
echo "::warning::Could not read the Gateway API conformance pin from ${GOMOD}; skipping the release check."
echo "latest=" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "pinned=${PINNED}" >> "$GITHUB_OUTPUT"
# /releases/latest excludes drafts and pre-releases, so release candidates
# (v1.6.0-rc1 and friends) never raise a false alarm.
LATEST=$(curl --fail --silent --show-error --max-time 30 \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
-H "Authorization: Bearer ${GH_TOKEN}" \
https://api.github.com/repos/kubernetes-sigs/gateway-api/releases/latest \
| jq -r '.tag_name // empty') || LATEST=""
# Validate before the value is ever interpolated into the chat payload
if ! printf '%s' "${LATEST}" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
echo "::warning::Could not resolve a usable latest Gateway API release tag (got '${LATEST}'); skipping the release check."
echo "latest=" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "Pinned Gateway API conformance version: ${PINNED}"
echo "Latest upstream Gateway API release: ${LATEST}"
# sort -V orders semver correctly (Ex: 1.10.0 after 1.9.0)
NEWEST=$(printf '%s\n%s\n' "${PINNED#v}" "${LATEST#v}" | sort -V | tail -n1)
if [ "${NEWEST}" = "${PINNED#v}" ]; then
echo "Pin is up to date."
echo "latest=" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "::notice::Gateway API ${LATEST} is available; the conformance suite is pinned to ${PINNED}."
echo "latest=${LATEST}" >> "$GITHUB_OUTPUT"
- name: Send Google Chat notification
env:
WEBHOOK_URL: ${{ secrets.GOOGLE_CHATSPACE_WEBHOOK_URL }}
# UPSTREAM_LATEST is empty unless a strictly newer Gateway API release exists;
UPSTREAM_LATEST: ${{ steps.upstream.outputs.latest }}
UPSTREAM_PINNED: ${{ steps.upstream.outputs.pinned }}
# needs.<job>.result is success/failure/cancelled; the status output adds
# detail (passed/failed/error). Passed via env to keep untrusted-looking
# context out of the inline shell.
RESULT: ${{ needs.conformance.result }}
STATUS: ${{ needs.conformance.outputs.status }}
REPO: ${{ github.repository }}
REF_NAME: ${{ github.ref_name }}
EVENT: ${{ github.event_name }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
set -euo pipefail
if [ -z "${WEBHOOK_URL}" ]; then
echo "GOOGLE_CHATSPACE_WEBHOOK_URL is not configured (e.g. a fork PR); skipping notification."
exit 0
fi
if [ "${RESULT}" = "success" ]; then
HEADLINE="✅ *Gateway API Conformance Passed*"
elif [ "${STATUS}" = "failed" ]; then
# A report was produced but some conformance tests failed.
HEADLINE="❌ *Gateway API Conformance Failed* — View Report: ${RUN_URL}"
else
# status=error, or empty because the job died before the report step
# (image build / cluster bring-up / install failure).
HEADLINE="🔥 *Gateway API Conformance Errored*"
fi
# Appended only when the release check found a newer upstream version.
UPSTREAM_LINE=""
if [ -n "${UPSTREAM_LATEST}" ]; then
UPSTREAM_LINE="\n🔔 *(Alert):* Gateway-API ${UPSTREAM_LATEST} is now available — this suite is pinned to ${UPSTREAM_PINNED}."
fi
# Create the final message payload
MESSAGE="${HEADLINE}\n*Repository:* ${REPO}\n*Ref:* ${REF_NAME}\n*Trigger:* ${EVENT}\n*Run:* ${RUN_URL}${UPSTREAM_LINE}"
PAYLOAD="$(jq -cn --arg text "${MESSAGE}" '{text: $text}')"
echo "${PAYLOAD}" | curl --fail --silent --show-error \
-X POST \
-H 'Content-Type: application/json' \
-d @- \
"${WEBHOOK_URL}"
echo "Notification sent to Google Chat."