Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
96509f7
feat: add Dockerized testing
maxday Apr 25, 2025
71d1062
feat: add new GitHub action workflow
maxday Apr 25, 2025
a96c509
feat: add new GitHub action workflow
maxday Apr 25, 2025
b3a4a88
feat: add new GitHub action workflow
maxday Apr 25, 2025
1ddf3e5
feat: add new GitHub action workflow
maxday Apr 25, 2025
4e58179
feat: add subset of tests
maxday Apr 25, 2025
3e50d3b
feat: add subset of tests
maxday Apr 25, 2025
025d79b
fix: action name
maxday Apr 25, 2025
0fa1c4d
fix: action name
maxday Apr 25, 2025
bb00157
fix: GitHub actions
maxday Apr 25, 2025
0a0d009
fix: GitHub actions
maxday Apr 25, 2025
bd2d027
fix: GitHub actions
maxday Apr 25, 2025
d14b739
fix: use main
maxday Apr 25, 2025
c88fe64
fix: bump version
maxday Apr 25, 2025
8fac4ae
Merge branch 'main' into maxday/add-dockerized-testing
maxday Feb 19, 2026
acd7c37
feat: use harness tests locally
maxday Feb 19, 2026
749c5c8
feat: clone the github action locally
maxday Feb 19, 2026
38f40fa
feat: clone the github action locally
maxday Feb 19, 2026
ef8eec4
fix: docker
maxday Feb 19, 2026
637e890
fix: tests
maxday Feb 19, 2026
7da1fde
fix: disable ctx test for now
maxday Feb 19, 2026
f23baf4
fix: restrict token permissions
maxday Feb 19, 2026
29411e7
fix: update dockerized-test.yml
maxday Feb 20, 2026
4c285e2
fix: update dockerized-test.yml
maxday Feb 20, 2026
ad24de9
fix: update dockerized-test.yml
maxday Feb 20, 2026
aa41c2b
fix: use docker
maxday Feb 20, 2026
c438509
fix: path
maxday Feb 20, 2026
16ac588
fix: docker
maxday Feb 20, 2026
bea0c50
feat: use docker
maxday Feb 23, 2026
1332fe2
fix: harness
maxday Feb 24, 2026
44d2fbf
fix: remove useless file
maxday Feb 24, 2026
746515b
fix: using main
maxday Feb 24, 2026
a504b6a
fix: update readme
maxday Feb 24, 2026
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
41 changes: 41 additions & 0 deletions .github/workflows/dockerized-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: dockerized-test

permissions:
contents: read

on:
push:
branches: [ main ]
pull_request:
branches: [ '*' ]
workflow_dispatch:


jobs:
dockerized-test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
ruby_version: ['3.3', '3.4']

steps:
- uses: actions/checkout@v3

- name: Set up ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby_version }}

- name: Build the lib
run: make build

- name: Build the image
run: docker build . -t local/test -f Dockerfile.test --build-arg BASE_IMAGE=public.ecr.aws/lambda/ruby:${{ matrix.ruby_version }}

- name: Run tests
uses: aws/containerized-test-runner-for-aws-lambda@main
with:
suiteFileArray: '["./test/dockerized/suites/*.json"]'
dockerImageName: 'local/test'
taskFolder: './test/dockerized/tasks'
Comment on lines 16 to 41

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 5 days ago

In general, you fix this issue by explicitly declaring a permissions: block either at the top level of the workflow (applies to all jobs) or under the specific job, granting only the scopes needed (typically contents: read for basic CI). Since this workflow only checks out code, sets up Ruby, builds, and runs tests, it appears to need only read access to repository contents, so contents: read is an appropriate minimal permission.

The best fix without changing existing functionality is to add a root-level permissions: block right after the name: (line 1) and before the on: block (line 3). This keeps the job definition intact and ensures any future jobs in this workflow inherit the same minimal permissions unless they override them. Concretely, in .github/workflows/dockerized-test.yml, insert:

permissions:
  contents: read

on new lines between current lines 1 and 3 (shifting the rest down). No additional methods, imports, or definitions are needed: this is a pure workflow configuration change.

Suggested changeset 1
.github/workflows/dockerized-test.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/dockerized-test.yml b/.github/workflows/dockerized-test.yml
--- a/.github/workflows/dockerized-test.yml
+++ b/.github/workflows/dockerized-test.yml
@@ -1,5 +1,8 @@
 name: dockerized-test
 
+permissions:
+  contents: read
+
 on:
   push:
     branches: [ main ]
EOF
@@ -1,5 +1,8 @@
name: dockerized-test

permissions:
contents: read

on:
push:
branches: [ main ]
Copilot is powered by AI and may make mistakes. Always verify output.
@maxday maxday committed this autofix suggestion 5 days ago.
Copy link
Member Author

Choose a reason for hiding this comment

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

fixed

4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,7 @@ test/examples/hello-world-docker/pkg
*.iml
.DS_Store
Gemfile.lock
# useful when using rbenv
.ruby-version
# containerized test runner clone
.test-runner/
8 changes: 8 additions & 0 deletions Dockerfile.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
ARG BASE_IMAGE
FROM $BASE_IMAGE
ENV GEM_HOME=/var/runtime
ADD test/dockerized/tasks /var/task
RUN gem uninstall aws_lambda_ric --executables
ADD pkg /tmp/pkg
RUN gem install /tmp/pkg/aws_lambda_ric-*.gem
RUN rm -rf /tmp/pkg
31 changes: 31 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,36 @@ build:
run-local-ric:
scripts/run-local-ric.sh

.PHONY: test-dockerized
test-dockerized:
@echo "Running dockerized tests locally..."
@if [ -z "$(RUBY_VERSION)" ]; then \
echo "Error: RUBY_VERSION is not set. Usage: make test-dockerized RUBY_VERSION=3.3"; \
exit 1; \
fi
@echo "Building the lib..."
$(MAKE) build
@echo "Building Docker image for Ruby $(RUBY_VERSION)..."
docker build . -t local/test -f Dockerfile.test --build-arg BASE_IMAGE=public.ecr.aws/lambda/ruby:$(RUBY_VERSION)
@echo "Setting up containerized test runner..."
@if [ ! -d ".test-runner" ]; then \
echo "Copying local containerized-test-runner-for-aws-lambda..."; \
cp -r ../containerized-test-runner-for-aws-lambda .test-runner; \
fi
@echo "Building test runner Docker image..."
@docker build -t test-runner:local -f .test-runner/Dockerfile .test-runner
@echo "Running tests in Docker..."
@docker run --rm \
--entrypoint suite \
-e DOCKER_API_VERSION=1.41 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v $(CURDIR)/test/dockerized/tasks:$(CURDIR)/test/dockerized/tasks:ro \
-v $(CURDIR)/test/dockerized/suites:/suites:ro \
test-runner:local \
--test-image local/test \
--debug \
/suites/*.json

.PHONY: pr
pr: init test-unit test-smoke

Expand All @@ -46,6 +76,7 @@ TARGETS
test-integ Run Integration tests.
test-unit Run Unit Tests.
test-smoke Run Sanity/Smoke tests.
test-dockerized Run dockerized tests locally (requires RUBY_VERSION=X.X).
run-local-ric Run local RIC changes with Runtime Interface Emulator.
pr Perform all checks before submitting a Pull Request.

Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,16 @@ Then,
* to run integration tests: `make test-integ`
* to run smoke tests: `make test-smoke`

### Running Dockerized Harness Tests

To run the containerized test harness locally, use:

```shell script
make test-dockerized RUBY_VERSION=3.4
```

This command builds your Lambda function in a Docker container using the specified Ruby version, sets up the containerized test runner, and executes the test suites defined in `test/dockerized/suites/`.

### Troubleshooting
While running integration tests, you might encounter the Docker Hub rate limit error with the following body:
```
Expand Down
78 changes: 78 additions & 0 deletions test/dockerized/suites/core.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
{
"tests": [
{
"name": "test_echo",
"handler": "core.ping",
"request": {
"msg": "message"
},
"assertions": [
{
"response": {
"msg": "pong[message]"
}
}
]
},
{
"name": "test_string_payload",
"handler": "core.str_ping",
"request": "message",
"assertions": [
{
"response": {
"msg": "pong[message]"
}
}
]
},
{
"name": "test_module_echo",
"handler": "core.HandlerClass.ping",
"request": {
"msg": "MyMessage"
},
"assertions": [
{
"response": "Module Message: 'MyMessage'"
}
]
},
{
"name": "test_deep_module_echo",
"handler": "core.DeepModule::Handler.ping",
"request": {
"msg": "MyMessage"
},
"assertions": [
{
"response": "Deep Module Message: 'MyMessage'"
}
]
},
{
"name": "test_error",
"handler": "core.broken",
"request": {
"msg": "message"
},
"assertions": [
{
"errorType": "Function<ArgumentError>"
}
]
},
{
"name": "test_string",
"handler": "core.string",
"request": {
"msg": "MyMessage"
},
"assertions": [
{
"response": "Message: 'MyMessage'"
}
]
}
]
}
49 changes: 49 additions & 0 deletions test/dockerized/suites/ctx.json.disabled
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"tests": [
{
"name": "test_ctx_cognito_pool_id",
"handler": "ctx.get_cognito_pool_id",
"cognitoIdentity": {
"cognitoIdentityId": "4ab95ea510c14353a7f6da04489c43b8",
"cognitoIdentityPoolId": "35ab4794a79a4f23947d3e851d3d6578"
},
"request": {},
"assertions": [
{
"response": {
"cognito_pool_id": "35ab4794a79a4f23947d3e851d3d6578"
}
}
]
},
{
"name": "test_ctx_cognito_identity_id",
"handler": "ctx.get_cognito_identity_id",
"cognitoIdentity": {
"cognitoIdentityId": "4ab95ea510c14353a7f6da04489c43b8",
"cognitoIdentityPoolId": "35ab4794a79a4f23947d3e851d3d6578"
},
"request": {},
"assertions": [
{
"response": {
"cognito_identity_id": "4ab95ea510c14353a7f6da04489c43b8"
}
}
]
},
{
"name": "get_remaining_time_in_millis | elapsedTime",
"handler": "ctx.get_remaining_time_from_context",
"request": {
"sleepTimeSeconds": 0.1
},
"assertions": [
{
"transform": ".elapsedTime >= 100",
"response": true
}
]
}
]
}
55 changes: 55 additions & 0 deletions test/dockerized/tasks/core.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.

def ping(event:, context:)
resp = {}
if event.nil?
resp[:event_nil] = true
else
resp[:msg] = "pong[#{event["msg"]}]"
end
puts "Hello, loggers!"
resp
end

def str_ping(event:, context:)
{ msg: "pong[#{event}]" }
end

def broken(_)
raise ArgumentError.new("My error message.")
end

def string(event:, context:)
"Message: '#{event["msg"]}'"
end

def curl(event:,context:)
resp = Net::HTTP.get(URI(event["url"]))
if resp.size > 0
{ success: true }
else
raise "Empty response!"
end
end

def io(_)
StringIO.new("This is IO!")
end

def execution_env(_)
{ "AWS_EXECUTION_ENV" => ENV["AWS_EXECUTION_ENV"] }
end

class HandlerClass
def self.ping(event:,context:)
"Module Message: '#{event["msg"]}'"
end
end

module DeepModule
class Handler
def self.ping(event:,context:)
"Deep Module Message: '#{event["msg"]}'"
end
end
end
32 changes: 32 additions & 0 deletions test/dockerized/tasks/ctx.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.

def get_context(event:,context:)
{
function_name: context.function_name,
deadline_ns: context.deadline_ns,
aws_request_id: context.aws_request_id,
invoked_function_arn: context.invoked_function_arn,
log_group_name: context.log_group_name,
log_stream_name: context.log_stream_name,
memory_limit_in_mb: context.memory_limit_in_mb,
function_version: context.function_version
}
end

def get_cognito_pool_id(event:,context:)
{ cognito_pool_id: context.identity&.dig("cognitoIdentityPoolId")}
end

def get_cognito_identity_id(event:,context:)
{ cognito_identity_id: context.identity&.dig("cognitoIdentityId") }
end

def echo_context(event:,context:)
context.client_context
end

def get_remaining_time_from_context(event:, context:)
before = context.get_remaining_time_in_millis()
sleep(event['sleepTimeSeconds'])
return { elapsedTime: before - context.get_remaining_time_in_millis() }
end
Loading