Skip to content

fix(headers): complete the exact-name rule, and carry the forward on /v1/realtime #709

fix(headers): complete the exact-name rule, and carry the forward on /v1/realtime

fix(headers): complete the exact-name rule, and carry the forward on /v1/realtime #709

# Real-cloud object_store smoke e2e — credential_ref (static-key) write path
# against REAL Amazon S3, Google Cloud Storage, and Azure Blob.
#
# Runs the `objstore_smoke_s3` / `objstore_smoke_gcs` / `objstore_smoke_azure`
# round-trips (write a batch
# → assert exactly one object under the prefix → re-deliver the same batch →
# assert no duplicate key → clean up) against the actual cloud APIs. These
# complement the emulator smoke in ci.yml's unit job, which cannot exercise real
# S3 auth or (for GCS) the real PUT path that fake-gcs-server can't round-trip.
#
# Gated: never runs on a normal push. Triggered manually (workflow_dispatch),
# nightly (schedule), or on a same-repo PR labeled `objstore real cloud`. Each
# provider's test self-skips (logged) when its secrets are absent, so an
# unconfigured run is a green no-op.
#
# ── Required repository secrets ──
# Settings → Secrets and variables → Actions → New repository secret
#
# Amazon S3 (native AWS):
# AISIX_E2E_OBJSTORE_S3_BUCKET test bucket name
# AISIX_E2E_OBJSTORE_S3_REGION the bucket's region, e.g. us-east-1
# AISIX_E2E_OBJSTORE_S3_ACCESS_KEY_ID IAM user access key id
# AISIX_E2E_OBJSTORE_S3_SECRET_ACCESS_KEY IAM user secret access key
# (For an S3-compatible host — MinIO / Cloudflare R2 — also set
# AISIX_E2E_OBJSTORE_S3_ENDPOINT.)
# Google Cloud Storage:
# AISIX_E2E_OBJSTORE_GCS_BUCKET test bucket name
# AISIX_E2E_OBJSTORE_GCS_SERVICE_ACCOUNT the full service-account key JSON
# (paste the downloaded key as one secret)
# Azure Blob:
# AISIX_E2E_OBJSTORE_AZURE_ACCOUNT storage account name
# AISIX_E2E_OBJSTORE_AZURE_ACCESS_KEY a storage account access key
# AISIX_E2E_OBJSTORE_AZURE_CONTAINER test container name
# (For Azurite instead of a real account, also set AISIX_E2E_OBJSTORE_AZURE_ENDPOINT.)
#
# Least privilege — scope the identity to the test bucket only:
# AWS: s3:PutObject, s3:GetObject, s3:DeleteObject on arn:aws:s3:::<bucket>/*
# + s3:ListBucket on arn:aws:s3:::<bucket>
# GCS: roles/storage.objectAdmin on the bucket
# Azure: an account key is account-wide, so use a DEDICATED test storage
# account (object_store's azure backend authenticates with account+key)
#
# See crates/aisix-obs/tests/real-cloud.env.example for a local-run template.
name: objstore-real-cloud
on:
workflow_dispatch:
schedule:
- cron: "30 0 * * *" # 00:30 UTC (08:30 Asia/Shanghai)
pull_request:
types: [labeled, synchronize, reopened]
branches: [main]
permissions:
contents: read
concurrency:
group: objstore-real-cloud-${{ github.ref }}
cancel-in-progress: true
jobs:
smoke:
name: objstore real-cloud smoke (S3 + GCS + Azure)
# Same-repo + label gate on PRs; always run on manual dispatch / schedule.
# The explicit same-repo check is defense-in-depth: plain `pull_request`
# withholds secrets from fork PRs by GitHub default today, but this gate
# keeps the credentials off fork-controlled code even if that default is
# ever flipped (mirrors docker-image.yml's `!= 'pull_request'` guard).
if: >-
github.event_name != 'pull_request' ||
(github.event.pull_request.head.repo.full_name == github.repository &&
contains(github.event.pull_request.labels.*.name, 'objstore real cloud'))
runs-on: ubuntu-latest
env:
AISIX_E2E_OBJSTORE_S3_BUCKET: ${{ secrets.AISIX_E2E_OBJSTORE_S3_BUCKET }}
AISIX_E2E_OBJSTORE_S3_REGION: ${{ secrets.AISIX_E2E_OBJSTORE_S3_REGION }}
AISIX_E2E_OBJSTORE_S3_ENDPOINT: ${{ secrets.AISIX_E2E_OBJSTORE_S3_ENDPOINT }}
AISIX_E2E_OBJSTORE_S3_ACCESS_KEY_ID: ${{ secrets.AISIX_E2E_OBJSTORE_S3_ACCESS_KEY_ID }}
AISIX_E2E_OBJSTORE_S3_SECRET_ACCESS_KEY: ${{ secrets.AISIX_E2E_OBJSTORE_S3_SECRET_ACCESS_KEY }}
AISIX_E2E_OBJSTORE_GCS_BUCKET: ${{ secrets.AISIX_E2E_OBJSTORE_GCS_BUCKET }}
AISIX_E2E_OBJSTORE_GCS_SERVICE_ACCOUNT: ${{ secrets.AISIX_E2E_OBJSTORE_GCS_SERVICE_ACCOUNT }}
AISIX_E2E_OBJSTORE_AZURE_ACCOUNT: ${{ secrets.AISIX_E2E_OBJSTORE_AZURE_ACCOUNT }}
AISIX_E2E_OBJSTORE_AZURE_ACCESS_KEY: ${{ secrets.AISIX_E2E_OBJSTORE_AZURE_ACCESS_KEY }}
AISIX_E2E_OBJSTORE_AZURE_CONTAINER: ${{ secrets.AISIX_E2E_OBJSTORE_AZURE_CONTAINER }}
AISIX_E2E_OBJSTORE_AZURE_ENDPOINT: ${{ secrets.AISIX_E2E_OBJSTORE_AZURE_ENDPOINT }}
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- uses: ./.github/actions/setup-protoc
- uses: Swatinem/rust-cache@v2
- name: Report which providers are configured
run: |
s3=0; gcs=0; azure=0
if [ -n "$AISIX_E2E_OBJSTORE_S3_BUCKET" ]; then echo "S3: configured"; s3=1; else echo "::warning::S3 secrets absent — objstore_smoke_s3 will self-skip"; fi
if [ -n "$AISIX_E2E_OBJSTORE_GCS_BUCKET" ]; then echo "GCS: configured"; gcs=1; else echo "::warning::GCS secrets absent — objstore_smoke_gcs will self-skip"; fi
if [ -n "$AISIX_E2E_OBJSTORE_AZURE_ACCOUNT" ]; then echo "Azure: configured"; azure=1; else echo "::warning::Azure secrets absent — objstore_smoke_azure will self-skip"; fi
# A manual dispatch or scheduled run is deliberate — secrets are
# expected. Fail rather than pass green while testing nothing. PR
# runs may legitimately have no secrets, so they still self-skip.
if [ "${{ github.event_name }}" != "pull_request" ] && [ "$s3" = 0 ] && [ "$gcs" = 0 ] && [ "$azure" = 0 ]; then
echo "::error::No object_store real-cloud secrets configured; this ${{ github.event_name }} run would test nothing."
exit 1
fi
- name: objstore real-cloud round-trips (S3 + GCS + Azure)
run: cargo test -p aisix-obs -- --ignored --nocapture objstore_smoke_s3 objstore_smoke_gcs objstore_smoke_azure