Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
d8bc2a7
feat(multi-runner): integrate Lambda MicroVM provider
edersonbrilhante Sep 3, 2026
4110ffa
docs: auto update terraform docs
github-actions[bot] Sep 8, 2026
1747ea5
fix(multi-runner): align v2 configuration tests
edersonbrilhante Sep 8, 2026
e41e27d
feat(microvm): add lifecycle hook service
edersonbrilhante Sep 3, 2026
360cdf9
test(microvm): remove legacy DynamoDB payload case
edersonbrilhante Sep 3, 2026
6f1ead8
fix(microvm): align storage environment export
edersonbrilhante Sep 8, 2026
8c1c06a
docs: auto update terraform docs
github-actions[bot] Sep 17, 2026
702d2e9
chore(pr): scope lifecycle hook change to service
edersonbrilhante Sep 17, 2026
2bcccbf
Merge branch 'feat-microvm-runner-provider' into feat-microvm-lifecyc…
edersonbrilhante Sep 17, 2026
8efc209
Merge branch 'feat-microvm-runner-provider' into feat-microvm-lifecyc…
edersonbrilhante Sep 17, 2026
a6aa30d
Merge branch 'feat-microvm-runner-provider' into feat-microvm-lifecyc…
edersonbrilhante Sep 18, 2026
890b456
Merge branch 'feat-microvm-runner-provider' into feat-microvm-lifecyc…
edersonbrilhante Sep 18, 2026
4afb4c7
chore(microvm): build and publish lifecycle hook (#5380)
edersonbrilhante Sep 18, 2026
c99ffef
chore(microvm): build lifecycle hook server
edersonbrilhante Sep 18, 2026
08732d7
Merge branch 'feat-microvm-runner-provider' into feat-microvm-lifecyc…
edersonbrilhante Sep 18, 2026
0cc81cf
test: fix microvm test with ministack
edersonbrilhante Sep 18, 2026
e70da22
Merge branch 'feat-microvm-runner-provider' into feat-microvm-lifecyc…
edersonbrilhante Sep 18, 2026
c31c050
docs: auto update terraform docs
github-actions[bot] Sep 18, 2026
10f0423
Merge branch 'feat-microvm-runner-provider' into feat-microvm-lifecyc…
edersonbrilhante Sep 18, 2026
73551e2
Merge branch 'feat-microvm-runner-provider' into feat-microvm-lifecyc…
edersonbrilhante Sep 18, 2026
99dc6e7
test: fix microvm variables
edersonbrilhante Sep 18, 2026
e3e57b1
feat(ministack): add multi-provider webhook smoke test
edersonbrilhante Sep 21, 2026
ebfdc93
docs: auto update terraform docs
github-actions[bot] Sep 21, 2026
27d8910
Merge branch 'feat-microvm-runner-provider' into feat-microvm-lifecyc…
edersonbrilhante Sep 21, 2026
b27dce2
docs: auto update terraform docs
github-actions[bot] Sep 21, 2026
ebb2fd4
Merge branch 'feat-microvm-runner-provider' into feat-microvm-lifecyc…
edersonbrilhante Sep 21, 2026
a924d33
fix(ministack): align webhook example provider locks
edersonbrilhante Sep 21, 2026
820d1d5
docs: auto update terraform docs
github-actions[bot] Sep 21, 2026
42565a2
fix: fix issue in tf 1.5.6
edersonbrilhante Sep 21, 2026
d3e6903
fix(storage): recognize wrapped SSM parameter errors
edersonbrilhante Sep 22, 2026
2d6ee5c
ci: use latest ministack version
edersonbrilhante Sep 22, 2026
a42e542
ci: fix ministack job
edersonbrilhante Sep 22, 2026
f0299db
docs(microvm): explain image and runtime dependencies (#5457)
edersonbrilhante Sep 22, 2026
3dd87d0
ci: fix dist
edersonbrilhante Sep 22, 2026
c9aeb9b
feat(microvm): add lifecycle hook runner startup
edersonbrilhante Sep 22, 2026
29534ed
Merge remote-tracking branch 'origin/feat-microvm-runner-provider' in…
edersonbrilhante Sep 22, 2026
97dd19e
Merge remote-tracking branch 'origin/feat-microvm-runner-provider' in…
edersonbrilhante Sep 22, 2026
5ea10d1
Merge remote-tracking branch 'origin/feat-microvm-runner-provider' in…
edersonbrilhante Sep 22, 2026
37d0b36
Merge remote-tracking branch 'origin/feat-microvm-runner-provider' in…
edersonbrilhante Sep 23, 2026
1951d82
test: fix smoke test
edersonbrilhante Sep 23, 2026
02d486d
Merge remote-tracking branch 'origin/feat-microvm-runner-provider' in…
edersonbrilhante Sep 23, 2026
977aef6
ci: fix job
edersonbrilhante Sep 23, 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: 40 additions & 1 deletion .github/workflows/lambda.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
with:
persist-credentials: false
- name: Install dependencies
run: yarn install --frozen-lockfile
run: yarn install --immutable --mode=skip-build
- name: Run prettier
run: yarn format-check
- name: Run linter
Expand All @@ -50,3 +50,42 @@ jobs:
name: coverage-reports
path: ./**/coverage
retention-days: 5

microvm-lifecycle-hooks:
name: Build MicroVM lifecycle hook
runs-on: ubuntu-latest
container:
image: node:24@sha256:aa648b387728c25f81ff811799bbf8de39df66d7e2d9b3ab55cc6300cb9175d9
defaults:
run:
working-directory: ./lambdas

steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
with:
egress-policy: audit

- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Install dependencies
run: yarn install --immutable --mode=skip-build

- name: Run prettier
run: yarn prettier --check "services/microvm-lifecycle-hooks/**/*.{ts,json,md}"

- name: Run linter
run: yarn eslint services/microvm-lifecycle-hooks/src

- name: Run tests
run: yarn nx test @aws-github-runner/microvm-lifecycle-hooks

- name: Build distribution
run: yarn workspace @aws-github-runner/microvm-lifecycle-hooks build

- name: Verify server distribution
run: |
test -s services/microvm-lifecycle-hooks/dist/server.js
test -f services/microvm-lifecycle-hooks/dist/package.json
2 changes: 0 additions & 2 deletions .github/workflows/ministack.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,9 @@ jobs:
- prebuilt
- default
- ephemeral
- microvm
- microvm-foundation
- migration-test
- multi-runner
- multi-runner-v2
- termination-watcher
services:
ministack:
Expand Down
80 changes: 60 additions & 20 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,21 @@ jobs:
persist-credentials: false
- name: Build dist
working-directory: lambdas
run: yarn install --frozen-lockfile && yarn run test && yarn dist
run: yarn install --immutable --mode=skip-build && yarn run test && yarn dist

- name: Build MicroVM lifecycle hook
working-directory: lambdas
run: yarn workspace @aws-github-runner/microvm-lifecycle-hooks build

- name: Verify MicroVM lifecycle hook distribution
working-directory: lambdas
run: |
test -s services/microvm-lifecycle-hooks/dist/server.js
test -f services/microvm-lifecycle-hooks/dist/package.json

- name: Package MicroVM lifecycle hook
working-directory: lambdas/services/microvm-lifecycle-hooks
run: (cd dist && zip -r ../microvm-lifecycle-hooks.zip .)
- name: Get installation token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
id: token
Expand All @@ -61,35 +75,48 @@ jobs:
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
with:
subject-path: '${{ github.workspace }}/lambdas/functions/**/*.zip'

- name: Attest MicroVM lifecycle hook
if: ${{ steps.release.outputs.releases_created == 'true' }}
id: lifecycle-hook-attest
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
with:
subject-path: '${{ github.workspace }}/lambdas/services/microvm-lifecycle-hooks/microvm-lifecycle-hooks.zip'

- name: Update release notes with attestation
if: ${{ steps.release.outputs.releases_created == 'true' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ github.event.inputs.version }}
TAG_NAME: ${{ steps.release.outputs.tag_name }}
ATTESTATION_URL: ${{ steps.attest.outputs.attestation-url }}
LIFECYCLE_HOOK_ATTESTATION_URL: ${{ steps.lifecycle-hook-attest.outputs.attestation-url }}
REPOSITORY: ${{ github.repository }}
run: |
version="${VERSION}"
tag_name="${TAG_NAME}"
attestation_url="${ATTESTATION_URL}"
lifecycle_hook_attestation_url="${LIFECYCLE_HOOK_ATTESTATION_URL}"
repository="${REPOSITORY}"
gh release view $version --json body -q '.body' > new-release-notes.md
gh release view "$tag_name" --json body -q '.body' > new-release-notes.md
echo "## Attestation" >> new-release-notes.md
echo "Attestation url: $attestation_url" >> new-release-notes.md
echo "Lambda attestation url: $attestation_url" >> new-release-notes.md
echo "MicroVM lifecycle hook attestation url: $lifecycle_hook_attestation_url" >> new-release-notes.md
echo "Verify the artifacts by running \`gh attestation verify <name_of_artifact> --repo ${repository}\`" >> new-release-notes.md
gh release edit $tag_name -F new-release-notes.md -t $tag_name
gh release edit "$tag_name" -F new-release-notes.md -t "$tag_name"

- name: Upload release assets
if: ${{ steps.release.outputs.releases_created == 'true' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG_NAME: ${{ steps.release.outputs.tag_name }}
run: |
tag_name="${TAG_NAME}"
for f in $(find . -name '*.zip'); do
gh release upload $tag_name $f
done
- name: Attach attestation
while IFS= read -r -d '' f; do
gh release upload "$tag_name" "$f"
done < <(find lambdas/functions -name '*.zip' -print0)
gh release upload "$tag_name" \
"lambdas/services/microvm-lifecycle-hooks/microvm-lifecycle-hooks.zip"

- name: Attach Lambda attestation
if: ${{ steps.release.outputs.releases_created == 'true' }}
env:
ATTESTATION_BUNDLE: ${{ steps.attest.outputs.bundle-path }}
Expand All @@ -99,13 +126,26 @@ jobs:
run: |
# rename attest bundle to github-aws-runners-terraform-aws-github-runner-attestation-$attestation-id.sigstore
# OpenSSF expects the attestation bundle to be named in this format (*.sigstore)
SIGSTORE_BUNDLE=$RUNNER_TEMP/github-aws-runners-terraform-aws-github-runner-attestation-${ATTESTATION_ID}.sigstore
INTOTO_BUNDLE=$RUNNER_TEMP/github-aws-runners-terraform-aws-github-runner-attestation-${ATTESTATION_ID}.intoto.jsonl
mv ${ATTESTATION_BUNDLE} $SIGSTORE_BUNDLE
if [ -z "$SIGSTORE_BUNDLE" ]; then
echo "No attestation bundle found, skipping attachment."
exit 0
fi
gh release upload $TAG_NAME "$SIGSTORE_BUNDLE"
cat ${SIGSTORE_BUNDLE} | jq -r '.dsseEnvelope | select(.payloadType == "application/vnd.in-toto+json").payload' | base64 -d | jq .> ${INTOTO_BUNDLE}
gh release upload $TAG_NAME "${INTOTO_BUNDLE}"
sigstore_bundle="$RUNNER_TEMP/github-aws-runners-terraform-aws-github-runner-attestation-${ATTESTATION_ID}.sigstore"
intoto_bundle="$RUNNER_TEMP/github-aws-runners-terraform-aws-github-runner-attestation-${ATTESTATION_ID}.intoto.jsonl"
cp "$ATTESTATION_BUNDLE" "$sigstore_bundle"
gh release upload "$TAG_NAME" "$sigstore_bundle"
jq -r '.dsseEnvelope | select(.payloadType == "application/vnd.in-toto+json").payload' "$sigstore_bundle" \
| base64 --decode > "$intoto_bundle"
gh release upload "$TAG_NAME" "$intoto_bundle"

- name: Attach MicroVM lifecycle hook attestation
if: ${{ steps.release.outputs.releases_created == 'true' }}
env:
ATTESTATION_BUNDLE: ${{ steps.lifecycle-hook-attest.outputs.bundle-path }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG_NAME: ${{ steps.release.outputs.tag_name }}
ATTESTATION_ID: ${{ steps.lifecycle-hook-attest.outputs.attestation-id }}
run: |
sigstore_bundle="$RUNNER_TEMP/github-aws-runners-microvm-lifecycle-hooks-attestation-${ATTESTATION_ID}.sigstore"
intoto_bundle="$RUNNER_TEMP/github-aws-runners-microvm-lifecycle-hooks-attestation-${ATTESTATION_ID}.intoto.jsonl"
cp "$ATTESTATION_BUNDLE" "$sigstore_bundle"
gh release upload "$TAG_NAME" "$sigstore_bundle"
jq -r '.dsseEnvelope | select(.payloadType == "application/vnd.in-toto+json").payload' "$sigstore_bundle" \
| base64 --decode > "$intoto_bundle"
gh release upload "$TAG_NAME" "$intoto_bundle"
17 changes: 11 additions & 6 deletions .github/workflows/smoke-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ name: "Smoke Tests"

on:
pull_request:
paths: ["**/*.tf", "**/*.hcl", ".github/workflows/smoke-tests.yml"]
paths:
- "**/*.tf"
- "**/*.hcl"
- "images/microvm-ubuntu/**"
- "lambdas/**"
- "tests/ministack/**"
- ".github/workflows/smoke-tests.yml"
workflow_dispatch:

concurrency:
Expand All @@ -26,10 +32,10 @@ jobs:
control_plane_smoke:
name: Run webhook and pool lifecycle smoke test against MiniStack
runs-on: ubuntu-latest
timeout-minutes: 30
timeout-minutes: 120
services:
ministack:
image: ghcr.io/ministackorg/ministack:1.5.13@sha256:ce3c906f2866ff953ce4c56f06b1fa3e453bc32e41c00de17b5f5a8672c5a42c
image: ministackorg/ministack-preview-build:pr-1808-d140da92
Comment thread
edersonbrilhante marked this conversation as resolved.
Dismissed
ports:
- 4566:4566
options: --add-host=host.docker.internal:host-gateway
Expand Down Expand Up @@ -66,8 +72,7 @@ jobs:
- name: Build smoke-test Lambda distributions
working-directory: lambdas
run: |
yarn workspace @aws-github-runner/webhook dist
yarn workspace @aws-github-runner/control-plane dist
yarn dist

- name: Start MockServer
id: mockserver
Expand All @@ -82,4 +87,4 @@ jobs:
MINISTACK_GITHUB_MOCK_HOST: host.docker.internal
MINISTACK_GITHUB_MOCK_PORT: "1080"
MINISTACK_GITHUB_MOCK_URL: ${{ steps.mockserver.outputs.url }}
run: sh tests/ministack/run-smoke.sh
run: python tests/ministack/run-smoke.py
2 changes: 0 additions & 2 deletions .github/workflows/terraform.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,8 @@ env:
prebuilt
ephemeral
termination-watcher
microvm
microvm-foundation
multi-runner
multi-runner-v2
external-managed-ssm-secrets
TEST_MODULES: |
modules/runners
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,6 @@ secrets.auto.tfvars

node_modules/
site/

__pycache__/
ministack-smoke-checklist.txt
3 changes: 1 addition & 2 deletions docs/examples/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ Examples are located in the [examples](https://github.com/github-aws-runners/ter
- _[Default](default.md)_: The default example of the module
- _[Ephemeral](ephemeral.md)_: Example usages of ephemeral runners based on the default example.
- _[Multi Runner](multi-runner.md)_ : Example usage of creating a multi runner which creates multiple runners/ configurations with a single deployment. The examples including: "arm64", "windows", and "ubuntu" runners.
- _[Multi Runner v2](multi-runner-v2.md)_ : Example usage of the experimental v2 multi-runner configuration interface with shared defaults and per-lane overrides.
- _[Multi Runner Webhook](multi-runner-webhook.md)_: Example usage of one webhook deployment serving EC2 and Lambda MicroVM runner lanes.
- _[Permissions boundary](permissions-boundary.md)_: Example usages of permissions boundaries.
- _[Prebuilt Images](prebuilt.md)_: Example usages of deploying runners with a custom prebuilt image.
- _[Termination watcher](termination-watcher.md)_: Example usages of termination watcher.
- _[Dedicated Mac Hosts](dedicated-mac-hosts.md)_: Example usage of setting up dedicated hosts for macOS runners.
- _[Externally managed SSM secrets](external-managed-ssm-secrets.md)_: Example usage of externally managed SSM secrets for the GitHub App credentials.
- _[MicroVM foundation](microvm-foundation.md)_: Example usage of the regional Lambda MicroVM image-build and Network Connector prerequisites.
- _[Lambda MicroVM](microvm.md)_: Example usage of Linux ARM64 ephemeral runners backed by Lambda MicroVM images.
3 changes: 0 additions & 3 deletions docs/examples/microvm.md

This file was deleted.

1 change: 0 additions & 1 deletion docs/examples/multi-runner-v2.md

This file was deleted.

1 change: 1 addition & 0 deletions docs/examples/multi-runner-webhook.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--8<-- "examples/multi-runner-webhook/README.md"
129 changes: 129 additions & 0 deletions docs/microvm-runners.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# Lambda MicroVM Runners (Experimental)

!!! warning
Lambda MicroVM runner support is experimental. The image build, lifecycle-hook server, control-plane integration, and AWS MicroVM APIs must be configured together. Validate the complete flow in a non-production environment before relying on it for workloads.

## Overview

Lambda MicroVM runners provide ephemeral GitHub Actions runners backed by
Lambda MicroVMs. The runner control plane receives demand, obtains the
one-time runner configuration, starts a MicroVM from a published image, and
passes the runtime execution role to the MicroVM.

The repository includes a combined [multi-runner webhook example](examples/multi-runner-webhook.md)
that places EC2 and Lambda MicroVM lanes behind one webhook endpoint. The
provider-specific lifecycle checks are shared where possible, so the same
deployment can validate both providers.

## Prerequisites

Before deploying the MicroVM runner lane, prepare all of the following in the
target AWS Region:

1. **MicroVM foundation.** Apply the
[MicroVM foundation example](examples/microvm-foundation.md). It creates the
regional artifact bucket, Lambda Network Connectors, the image-build role,
and the reusable MicroVM usage policy.
2. **Lifecycle-hook artifact.** Build and release
`lambdas/services/microvm-lifecycle-hooks` through the same workspace
artifact process used for the repository's Lambda services. The resulting
ZIP is embedded in the MicroVM image.
3. **Published MicroVM image.** Use the
[MicroVM Ubuntu image instructions](https://github.com/github-aws-runners/terraform-aws-github-runner/blob/main/images/microvm-ubuntu/README.md)
to build and publish an image with Packer. The image must contain the
compatible lifecycle-hook server and runner entrypoint.
4. **Runner execution role.** Configure the runner role through the runner
configuration. This is different from the foundation's build role. The
control-plane TypeScript passes the execution role to `RunMicrovm`, so the
Lambda that starts the MicroVM must have permission to pass it.
5. **Runner control plane and artifacts.** Deploy the runner control plane with
the published image ARN/version, Network Connector ARNs, GitHub App
configuration, and the runner-control and webhook Lambda ZIPs.

The foundation does not create the image or the runner execution role. The
image build does not choose the runtime role. These are separate dependencies
owned by the image build and runner-control-plane stages respectively.

## IAM roles

MicroVM deployments use two roles for two different operations:

| Role | Used by | Responsibility |
| --- | --- | --- |
| Build role (`build_role_arn`) | Packer/image publisher | Creates and publishes the MicroVM image and accesses the foundation build artifacts. |
| Execution role | Runner control plane and the MicroVM | Is passed to `RunMicrovm` and provides the permissions used by the ephemeral runner at runtime. |

Do not use the build role as the runner execution role. The control-plane
Lambda needs `iam:PassRole` for the configured execution role, and the
execution role must contain the runtime permissions required by the selected
runner lane.

## Deployment order

The complete dependency chain is:

```text
MicroVM foundation
|
v
Build/release lifecycle-hook server
|
v
Packer builds and publishes image
|
v
Runner control plane resolves execution role
|
v
RunMicrovm starts an ephemeral runner
```

The lifecycle-hook server is part of the image artifact. Updating the hook
server therefore requires building/releasing the artifact and publishing a
new compatible image before deploying that image version to the runner lane.

## Combined EC2 and MicroVM deployment

The [multi-runner webhook example](examples/multi-runner-webhook.md) accepts
explicit `runners_lambda_zip` and `webhook_lambda_zip` inputs and configures
both compute providers behind one webhook. Its MicroVM settings require a
published image:

```hcl
compute_provider = {
aws = {
microvm = {
image_arn = "arn:aws:lambda:eu-west-1:123456789012:microvm-image:gha-ubuntu-arm64"
image_version = null
ingress_network_connectors = []
egress_network_connectors = ["arn:aws:lambda:eu-west-1:123456789012:network-connector:example"]
}
}
}
```

Use the example's complete Terraform configuration as the source of truth for
the current input shape. The example deploys the control plane; it does not
build the foundation, lifecycle-hook artifact, or MicroVM image for you.

## Known limitations

- This integration is experimental and depends on AWS Lambda MicroVM APIs and
the lifecycle-hook protocol.
- A compatible lifecycle-hook server must be present in every image used by
the MicroVM provider.
- Image publication and activation are separate from Terraform deployment;
wait for the image version to become active before starting jobs.
- The build role and execution role are intentionally separate. Changes to
either role can affect a different stage of the lifecycle.
- The combined webhook example is useful for integration testing, but a real
deployment still needs a real MicroVM image and the network/runtime IAM
configuration described above.

## Repository examples

- [MicroVM foundation](examples/microvm-foundation.md)
- [MicroVM image build README](https://github.com/github-aws-runners/terraform-aws-github-runner/blob/main/images/microvm-ubuntu/README.md)
- [Lifecycle-hook service README](https://github.com/github-aws-runners/terraform-aws-github-runner/blob/main/lambdas/services/microvm-lifecycle-hooks/README.md)
- [Multi-runner webhook](examples/multi-runner-webhook.md)
- [MicroVM foundation module](modules/public/microvm-foundation.md)
Loading
Loading