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
24 changes: 24 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,27 @@ jobs:
gh release upload "$TAG" \
--repo "$GITHUB_REPOSITORY" \
artifacts/*

smoke-test:
needs: upload
runs-on: ${{ matrix.runner }}
timeout-minutes: 15
permissions:
contents: write

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why do we need write permission for running smoke tests?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Draft releases are only visible to tokens with push access, so the download step needs contents: write.

strategy:
fail-fast: true
matrix:
include:
- arch: x86_64
runner: ubuntu-latest
- arch: aarch64
runner: ubuntu-24.04-arm
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: ${{ github.ref_name }}

- name: OCI + RIE smoke test against the published artifact
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: ci/integ/run-oci-smoke.sh "${{ matrix.arch }}" "${{ github.ref_name }}"
20 changes: 20 additions & 0 deletions ci/integ/docker/Dockerfile.oci-smoke
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Post-release OCI smoke test image.
#
# This links a dummy handler against the PREBUILT static library downloaded
# from the release (context file `runtime.a`), the point is we do NOT rebuild the runtime
FROM public.ecr.aws/amazonlinux/amazonlinux:2023 AS builder

RUN dnf install -y gcc-c++ libcurl-devel && dnf clean all

WORKDIR /build
COPY include/ include/
COPY runtime.a runtime.a
COPY main.cpp main.cpp

RUN g++ -std=c++11 -O2 -Iinclude main.cpp runtime.a -lcurl -pthread -o bootstrap

FROM public.ecr.aws/lambda/provided:al2023

COPY --from=builder /build/bootstrap ${LAMBDA_RUNTIME_DIR}/bootstrap

CMD [ "function.handler" ]
19 changes: 19 additions & 0 deletions ci/integ/oci/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include <aws/lambda-runtime/runtime.h>

using namespace aws::lambda_runtime;

// Dummy handler used by the post-release OCI smoke test. It echoes the incoming
// payload back and reports its length, which the smoke test asserts on.
static invocation_response my_handler(invocation_request const& req)
{
return invocation_response::success(
R"({"message":"hello from aws-lambda-cpp","echo":)" + (req.payload.empty() ? std::string("null") : req.payload) +
R"(,"payload_length":)" + std::to_string(req.payload.length()) + "}",
"application/json");
}

int main()
{
run_handler(my_handler);
return 0;
}
81 changes: 81 additions & 0 deletions ci/integ/run-oci-smoke.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/bin/bash
# Post-release OCI smoke test.
#
# Downloads the published static library from the (draft) release, verifies its
# checksum against the published SHA256SUMS, links a dummy handler against it,
# and invokes it through the Lambda Runtime Interface Emulator baked into
# public.ecr.aws/lambda/provided:al2023 — i.e. the exact happy path a downstream
# consumer of the artifact would follow.
#
# Requires: gh (with GH_TOKEN), docker, curl. Runs on stock GitHub-hosted
# runners; needs no AWS credentials or CodeArtifact access.
#
# Usage: run-oci-smoke.sh <arch> <tag>
set -euo pipefail

ARCH=${1:?usage: run-oci-smoke.sh <arch> <tag>}
TAG=${2:?usage: run-oci-smoke.sh <arch> <tag>}
REPO=${GITHUB_REPOSITORY:-awslabs/aws-lambda-cpp}
PORT=9000

SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
REPO_ROOT=$(cd "$SCRIPT_DIR/../.." && pwd)

LIB="libaws-lambda-runtime-${ARCH}.a"
IMAGE="lambda-cpp-oci-smoke:${ARCH}"
CONTAINER="lambda-cpp-oci-smoke-${ARCH}"

WORKDIR=$(mktemp -d)
trap 'docker rm -f "$CONTAINER" >/dev/null 2>&1 || true; rm -rf "$WORKDIR"' EXIT

echo "== Downloading $LIB + SHA256SUMS from release '$TAG' =="
gh release download "$TAG" --repo "$REPO" \
-p "$LIB" -p SHA256SUMS --dir "$WORKDIR" --clobber

echo "== Verifying checksum =="
( cd "$WORKDIR" && grep -F "$LIB" SHA256SUMS | sha256sum -c - )

echo "== Assembling build context =="
CTX="$WORKDIR/ctx"
mkdir -p "$CTX"
cp -r "$REPO_ROOT/include" "$CTX/include"
cp "$REPO_ROOT/ci/integ/oci/main.cpp" "$CTX/main.cpp"
cp "$WORKDIR/$LIB" "$CTX/runtime.a"

echo "== Building OCI image =="
docker build \
-f "$REPO_ROOT/ci/integ/docker/Dockerfile.oci-smoke" \
-t "$IMAGE" "$CTX"

echo "== Starting container (RIE) =="
docker run -d --name "$CONTAINER" -p "$PORT:8080" "$IMAGE" >/dev/null

INVOKE_URL="http://localhost:${PORT}/2015-03-31/functions/function/invocations"

echo "== Waiting for RIE to become ready =="
ready=false
for _ in $(seq 1 30); do
if curl -sf -XPOST "$INVOKE_URL" -d '{}' >/dev/null 2>&1; then
ready=true
break
fi
sleep 1
done
if [ "$ready" != true ]; then
echo "::error::RIE did not become ready in time"
docker logs "$CONTAINER" || true
exit 1
fi

echo "== Invoking via RIE =="
RESPONSE=$(curl -s -XPOST "$INVOKE_URL" -d '{"answer":42}')
echo "Response: $RESPONSE"

EXPECTED='"payload_length":13'
if ! echo "$RESPONSE" | grep -qF "$EXPECTED"; then
echo "::error::Smoke test assertion failed for $ARCH. Expected response to contain: $EXPECTED"
docker logs "$CONTAINER" || true
exit 1
fi

echo "Smoke test passed for $ARCH"
Loading