integration tests against sandbox aws account#712
Conversation
📝 WalkthroughWalkthroughAdds an opt-in live AWS integration test system: environment gating, run-id/project provisioning, Serverless/AWS helpers, four gated integration suites (evaluate, deploy, caching, domain), a leaked-resource sweeper, Jest/TS config and npm scripts, plus a manual GitHub Actions workflow and documentation. ChangesLive AWS Integration Testing Infrastructure
Sequence DiagramsequenceDiagram
participant CI as GitHub Actions
participant Runner as Workflow Runner
participant Build as Build Step
participant Tests as Integration Tests
participant AWS as AWS Services
participant Sweeper as Resource Sweeper
CI->>Runner: workflow_dispatch
Runner->>Build: checkout & setup (Node, npm ci)
Build->>Tests: npm run test:integration (jest)
Tests->>AWS: Tier A: evaluate (no deploy)
Tests->>AWS: Tier B: deploy & live CLI commands
Tests->>AWS: Tier C: caching commands
Tests->>AWS: Tier D: domain provisioning
Runner->>Sweeper: npm run test:integration:sweep (always)
Sweeper->>AWS: delete leaked AppSync APIs
Sweeper->>AWS: delete leaked CloudFormation stacks
Sweeper->>AWS: cleanup custom domains
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (2)
.github/workflows/integration.yml (1)
52-52: 💤 Low valuePin
aws-actions/configure-aws-credentialsto a commit SHA (ideally consistently across workflows).
integration.ymluses a floating tag (aws-actions/configure-aws-credentials@v4); since this action is commonly used for OIDC role assumption, pinning to a full commit SHA reduces supply-chain risk. Also, other workflows here already use floating tags (e.g.,actions/checkout@v4/actions/setup-node@v4in the same file,actions/checkout@v6/actions/setup-node@v6inci.yml,actions/checkout@v5/actions/setup-node@v5andsoftprops/action-gh-release@v2inrelease.yml), so consider adopting a repo-wide pinning policy rather than pinning only this one action.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/integration.yml at line 52, Replace the floating action tag aws-actions/configure-aws-credentials@v4 with a pinned full commit SHA for that action (and update any other workflow usages to the same pinned SHA for consistency); locate the line referencing aws-actions/configure-aws-credentials@v4 in the workflow and change it to the corresponding commit SHA from the action's repository, and consider applying the same pinning policy to other actions like actions/checkout and actions/setup-node across the repository so all workflows use fixed SHAs rather than floating tags.integration/helpers/sls.ts (1)
80-93: ⚡ Quick winSet an explicit
maxBufferforexecFileSync.
execFileSyncdefaults to a 1 MB stdout/stderr buffer. Adeploy/removewith verbose CloudFormation output can exceed this, causing anENOBUFSkill that surfaces as a spuriousSlsCommandErrorrather than the real deploy result.♻️ Proposed fix
const stdout = execFileSync(SERVERLESS_BIN, fullArgs, { cwd: options.cwd, timeout: options.timeout ?? 240_000, + maxBuffer: 64 * 1024 * 1024, env: {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@integration/helpers/sls.ts` around lines 80 - 93, The execFileSync call that runs Serverless (using SERVERLESS_BIN, fullArgs, and options) does not set maxBuffer and can overflow the default 1MB; update the options object passed to execFileSync in this helper (where stdio and env are set) to include a larger maxBuffer (e.g., 10*1024*1024 or 50*1024*1024) so verbose CloudFormation output won’t cause an ENOBUFS/SlsCommandError; keep the other env/stdio settings intact and ensure you apply the new maxBuffer to the same options object used by execFileSync.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/integration.yml:
- Line 42: Replace the default actions/checkout@v4 behavior so it does not
persist GITHUB_TOKEN into .git/config: update the checkout step referencing
actions/checkout@v4 to include persist-credentials: false (so the job
authenticates via OIDC only and no credentials are written to the repo config).
In `@doc/integration-tests.md`:
- Line 49: Update the Tier D env var entry so it references the full canonical
name instead of the truncated suffix: replace the `_HOSTED_ZONE_ID` fragment
used alongside `APPSYNC_PLUGIN_INTEGRATION_DOMAIN` with the complete
`APPSYNC_PLUGIN_INTEGRATION_HOSTED_ZONE_ID` variable name (matching the
documented canonical name used elsewhere) so the table entry and any examples
use `APPSYNC_PLUGIN_INTEGRATION_DOMAIN` +
`APPSYNC_PLUGIN_INTEGRATION_HOSTED_ZONE_ID`.
In `@integration/helpers/aws.ts`:
- Around line 167-173: The current check uses client.send(new
ListDomainNamesCommand({ maxResults: 25 })) and only inspects domainNameConfigs
for a match, which misses domains on later pages; replace this single-call
lookup with a paginated loop (similar to findLeakedApis/findLeakedStacks) that
repeatedly calls ListDomainNamesCommand using nextToken until all pages are
consumed or a domainName match is found, then set exists accordingly and only
return when no pages remain and no match was found; update the logic around
domainNameConfigs/exists to use the paginated result.
- Around line 174-183: The catch block around client.send(new
GetApiAssociationCommand({ domainName })) / DisassociateApiCommand currently
swallows all errors; change it so only the NotFoundException is ignored and all
other errors are propagated (or rethrown) so real failures surface.
Specifically, in the catch for the try containing GetApiAssociationCommand and
DisassociateApiCommand, detect whether err is an Error and err.name ===
'NotFoundException' and return/do-nothing only in that case; for any other error
(including non-Error values) rethrow (or throw a new Error preserving the
original) so permission/throttling/other failures are not silently swallowed.
In `@integration/sweeper.ts`:
- Around line 46-91: The sweeper currently swallows per-resource errors in
main() (during deleteApi, cleanupDomainName, deleteStack) so process exits 0
even when deletions fail; add failure tracking inside main: introduce a boolean
or counter (e.g., hadFailures or failureCount) and set it when any catch block
catches an error for deleteApi, cleanupDomainName, or deleteStack, then after
all work if hadFailures is true set process.exitCode = 1 (or throw an Error) so
the CI run fails; update log messages unchanged but ensure the catch blocks for
those functions update the shared failure flag.
---
Nitpick comments:
In @.github/workflows/integration.yml:
- Line 52: Replace the floating action tag
aws-actions/configure-aws-credentials@v4 with a pinned full commit SHA for that
action (and update any other workflow usages to the same pinned SHA for
consistency); locate the line referencing
aws-actions/configure-aws-credentials@v4 in the workflow and change it to the
corresponding commit SHA from the action's repository, and consider applying the
same pinning policy to other actions like actions/checkout and
actions/setup-node across the repository so all workflows use fixed SHAs rather
than floating tags.
In `@integration/helpers/sls.ts`:
- Around line 80-93: The execFileSync call that runs Serverless (using
SERVERLESS_BIN, fullArgs, and options) does not set maxBuffer and can overflow
the default 1MB; update the options object passed to execFileSync in this helper
(where stdio and env are set) to include a larger maxBuffer (e.g., 10*1024*1024
or 50*1024*1024) so verbose CloudFormation output won’t cause an
ENOBUFS/SlsCommandError; keep the other env/stdio settings intact and ensure you
apply the new maxBuffer to the same options object used by execFileSync.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d2c43fc7-53d4-4131-a416-0926f5acc0f3
📒 Files selected for processing (17)
.github/workflows/integration.ymldoc/integration-tests.mdintegration/caching.integration.test.tsintegration/deploy.integration.test.tsintegration/domain.integration.test.tsintegration/eval.integration.test.tsintegration/helpers/aws.tsintegration/helpers/config.tsintegration/helpers/gate.tsintegration/helpers/project.tsintegration/helpers/run-id.tsintegration/helpers/sls.tsintegration/sweeper.tsjest.integration.config.tsjest.integration.setup.tspackage.jsontsconfig.integration.json
Sibling to the offline e2e suite, exercising the plugin's live AWS code paths (post AWS-SDK-v3 migration in #686) against a real account. Opt-in via APPSYNC_PLUGIN_INTEGRATION=1; skips cleanly and is excluded from npm test / test:e2e / test:all and default CI. - Tier A: appsync evaluate (VTL + JS), no deploy - Tier B: minimal deploy -> info/get-introspection/env/logs + the credential/region proof for #686 - Tier C: caching/flush-cache (gated) - Tier D: custom domain + Route53 + ACM (gated, off by default) - run-id tagging + serverless remove teardown + standalone sweeper - doc/integration-tests.md, optional OIDC workflow (manual/scheduled)
e7ee83e to
498318e
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/integration.yml:
- Around line 29-32: The workflow's concurrency.group currently uses
integration-${{ github.ref }} which only serializes runs per ref; update the
concurrency.group to use a constant or environment-scoped account identifier so
runs are serialized per AWS account (e.g., replace integration-${{ github.ref }}
with a fixed key or integration-${{ env.AWS_ACCOUNT_ID }} / integration-${{
secrets.AWS_ACCOUNT_ID }}), keeping the concurrency block and cancel-in-progress
behavior intact; modify the workflow to ensure AWS account ID is provided to the
job environment (or use a fixed literal) so the concurrency.group truly enforces
one live suite per account.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: f8bc5b82-7328-4faa-a328-72fb471576c1
📒 Files selected for processing (17)
.github/workflows/integration.ymldoc/integration-tests.mdintegration/caching.integration.test.tsintegration/deploy.integration.test.tsintegration/domain.integration.test.tsintegration/eval.integration.test.tsintegration/helpers/aws.tsintegration/helpers/config.tsintegration/helpers/gate.tsintegration/helpers/project.tsintegration/helpers/run-id.tsintegration/helpers/sls.tsintegration/sweeper.tsjest.integration.config.tsjest.integration.setup.tspackage.jsontsconfig.integration.json
✅ Files skipped from review due to trivial changes (1)
- doc/integration-tests.md
🚧 Files skipped from review as they are similar to previous changes (11)
- jest.integration.setup.ts
- integration/eval.integration.test.ts
- package.json
- tsconfig.integration.json
- integration/sweeper.ts
- integration/helpers/run-id.ts
- integration/caching.integration.test.ts
- integration/helpers/config.ts
- integration/deploy.integration.test.ts
- integration/helpers/project.ts
- integration/helpers/sls.ts
| concurrency: | ||
| # Never run two live suites against the same account at once. | ||
| group: integration-${{ github.ref }} | ||
| cancel-in-progress: false |
There was a problem hiding this comment.
Concurrency group keyed by github.ref doesn't enforce the stated account-wide serialization.
The comment states this should "Never run two live suites against the same account at once," but group: integration-${{ github.ref }} only serializes runs originating from the same ref. Two dispatches from different branches/tags map to different groups and will run concurrently against the same AWS account. Use a constant (or environment-scoped) group key to actually serialize per account.
🔒 Proposed fix
concurrency:
# Never run two live suites against the same account at once.
- group: integration-${{ github.ref }}
+ group: integration
cancel-in-progress: false📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| concurrency: | |
| # Never run two live suites against the same account at once. | |
| group: integration-${{ github.ref }} | |
| cancel-in-progress: false | |
| concurrency: | |
| # Never run two live suites against the same account at once. | |
| group: integration | |
| cancel-in-progress: false |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/integration.yml around lines 29 - 32, The workflow's
concurrency.group currently uses integration-${{ github.ref }} which only
serializes runs per ref; update the concurrency.group to use a constant or
environment-scoped account identifier so runs are serialized per AWS account
(e.g., replace integration-${{ github.ref }} with a fixed key or integration-${{
env.AWS_ACCOUNT_ID }} / integration-${{ secrets.AWS_ACCOUNT_ID }}), keeping the
concurrency block and cancel-in-progress behavior intact; modify the workflow to
ensure AWS account ID is provided to the job environment (or use a fixed
literal) so the concurrency.group truly enforces one live suite per account.
…t, checkout hardening)
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
integration/helpers/aws.ts (1)
119-130:⚠️ Potential issue | 🟡 Minor | ⚡ Quick win
DELETE_FAILEDstacks are not swept and will leak.The
StackStatusFilterlists terminal create/update/rollback states but omitsDELETE_FAILED. If a previousdeleteStack(orserverless remove) left a stack inDELETE_FAILED,findLeakedStackswon't return it, so the sweeper silently skips it and the billable resources persist.🛡️ Proposed fix
StackStatusFilter: [ 'CREATE_COMPLETE', 'UPDATE_COMPLETE', 'ROLLBACK_COMPLETE', 'UPDATE_ROLLBACK_COMPLETE', 'CREATE_FAILED', 'ROLLBACK_FAILED', + 'DELETE_FAILED', ],🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@integration/helpers/aws.ts` around lines 119 - 130, The StackStatusFilter passed to ListStacksCommand inside findLeakedStacks (where ListStacksCommand and variables StackSummaries/NextToken are used) omits the DELETE_FAILED status so stacks in DELETE_FAILED are not returned and leak; update the StackStatusFilter array used in the ListStacksCommand call to include 'DELETE_FAILED' so those stacks are returned and can be swept. Ensure only the StackStatusFilter array is changed (add 'DELETE_FAILED') and keep pagination/NextToken handling unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@integration/helpers/aws.ts`:
- Around line 119-130: The StackStatusFilter passed to ListStacksCommand inside
findLeakedStacks (where ListStacksCommand and variables StackSummaries/NextToken
are used) omits the DELETE_FAILED status so stacks in DELETE_FAILED are not
returned and leak; update the StackStatusFilter array used in the
ListStacksCommand call to include 'DELETE_FAILED' so those stacks are returned
and can be swept. Ensure only the StackStatusFilter array is changed (add
'DELETE_FAILED') and keep pagination/NextToken handling unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 4dead1ef-fa9d-4919-968d-a27ea52ae650
📒 Files selected for processing (5)
.github/workflows/integration.ymldoc/integration-tests.mdintegration/helpers/aws.tsintegration/helpers/sls.tsintegration/sweeper.ts
✅ Files skipped from review due to trivial changes (1)
- doc/integration-tests.md
🚧 Files skipped from review as they are similar to previous changes (2)
- .github/workflows/integration.yml
- integration/helpers/sls.ts
| # Extra guard: only runs from the canonical repo, never a fork. | ||
| if: github.repository == 'sid88in/serverless-appsync-plugin' | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 45 |
There was a problem hiding this comment.
@sid88in how about 5 minutes? 45 looks like too big value.
| # into .git/config, since npm ci + the suite run third-party code. | ||
| persist-credentials: false | ||
|
|
||
| - uses: actions/setup-node@v4 |
|
|
||
| - uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: 20 |
There was a problem hiding this comment.
@sid88in aws lambda supports Node.js 22, and 24, let's avoid 20.
|
@sid88in before merging this PR please check that integration folder will not be included in npm build. Option 1: Update .npmignore (preferred) Option 2: Use files field in package.json (most explicit) |

Live AWS integration tests
This is an opt-in test suite that exercises the plugin's live AWS code
paths (the ones the AWS SDK v3 migration in #686
most affects) against a real AWS account. It is complementary to:
npm test— unit tests (src/__tests__), no AWS.npm run test:e2e— offline CloudFormation-synthesis tests (e2e/), no AWS.Unlike those, the integration suite costs money and needs credentials, so it
never runs in the default CI or as part of
npm test/npm run test:e2e/npm run test:all. It is gated behind theAPPSYNC_PLUGIN_INTEGRATIONenvironment variable and, when that is unset, every suite resolves to
describe.skipand the run exits green.What it proves
Each scenario maps to a live command and the SDK call it validates:
appsync evaluate --templateEvaluateMappingTemplateappsync evaluate --type/--fieldEvaluateCodeserverless infoListApiKeys,GetGraphqlApi,DescribeStackResourcesappsync get-introspectionGetIntrospectionSchemaappsync env set/env getPut/GetGraphqlApiEnvironmentVariablesappsync logsFilterLogEvents(CloudWatch Logs)appsync flush-cacheFlushApiCacheappsync domain createListCertificates(ACM, us-east-1 pin) +CreateDomainNameappsync domain assocGetApiAssociation(+NotFoundExceptionpath) +AssociateApiappsync domain create-recordListHostedZonesByName+ChangeResourceRecordSets+GetChange(poll → INSYNC)The credential/region proof is the most valuable test: it deploys with an
explicit
--region(and optional--aws-profile), asserts the API actuallylanded in that region (by reading the stack's AppSync API ARN), confirms a live
command pointed at that region succeeds, and confirms the same command pointed
at a different region fails to find the API — demonstrating that the live
commands honor the region resolved from the Serverless provider, not the bare
default credential chain.
Tiers and gating
APPSYNC_PLUGIN_INTEGRATION=1)APPSYNC_PLUGIN_INTEGRATION_CACHING=1APPSYNC_PLUGIN_INTEGRATION_DOMAIN+_HOSTED_ZONE_IDTiers are independently skippable: with only credentials set you get A and B;
caching and domain stay skipped until you opt in.
Running it
Environment variables
APPSYNC_PLUGIN_INTEGRATION1.APPSYNC_PLUGIN_INTEGRATION_REGIONus-west-2). Choose something other thanus-east-1so the ACM us-east-1 pin and the region proof are meaningful.APPSYNC_PLUGIN_INTEGRATION_PROFILEAPPSYNC_PLUGIN_INTEGRATION_OTHER_REGIONAPPSYNC_PLUGIN_INTEGRATION_EXPECTED_ACCOUNT_IDAPPSYNC_PLUGIN_INTEGRATION_CACHING1to run the caching tier.APPSYNC_PLUGIN_INTEGRATION_DOMAINit.example.com).APPSYNC_PLUGIN_INTEGRATION_HOSTED_ZONE_IDAPPSYNC_PLUGIN_INTEGRATION_CERT_ARNListCertificates.SERVERLESS_BINStandard AWS credential variables (
AWS_PROFILE,AWS_ACCESS_KEY_ID, OIDCAWS_ROLE_ARN, …) are honored as usual.Typecheck only
npm run test:integration:typecheck # tsc -p tsconfig.integration.jsonTeardown and leaked-resource recovery
Reliable teardown is the suite's top priority:
appsync-plugin-it-<ts>-<rand>)and tagged
appsync-plugin-integration: <run id>.serverless removeinafterAll(runs even onfailure). The custom-domain tier additionally deletes its non-CloudFormation
resources (Route53 record → API association → domain name) in reverse order.
The ACM certificate is reused, never created, and never deleted.
APPSYNC_PLUGIN_INTEGRATION=1 \ APPSYNC_PLUGIN_INTEGRATION_REGION=us-west-2 \ AWS_PROFILE=my-sandbox \ [APPSYNC_PLUGIN_INTEGRATION_DOMAIN=it.example.com] \ npm run test:integration:sweepThe sweeper deletes AppSync APIs tagged by the suite, CloudFormation stacks
named with the run-id prefix, and (if a domain is configured) a leaked custom
domain name. It is idempotent and safe to re-run. CloudFormation stack deletes
are asynchronous — verify completion in the console.
Least-privilege IAM policy
The actions actually used by the suite are below. Note that a
serverless deployis itself a CloudFormation operation that creates an AppSync API, anAPI key, a CloudWatch log group + logging role, and an S3 deployment bucket;
fully constraining a deploy role is involved, so in a throwaway sandbox account
many teams simply use a broader deploy role. The policy below is the scoped
target.
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AppSync", "Effect": "Allow", "Action": [ "appsync:CreateGraphqlApi", "appsync:DeleteGraphqlApi", "appsync:UpdateGraphqlApi", "appsync:GetGraphqlApi", "appsync:ListGraphqlApis", "appsync:StartSchemaCreation", "appsync:GetSchemaCreationStatus", "appsync:GetIntrospectionSchema", "appsync:CreateApiKey", "appsync:DeleteApiKey", "appsync:ListApiKeys", "appsync:CreateDataSource", "appsync:DeleteDataSource", "appsync:UpdateDataSource", "appsync:CreateResolver", "appsync:DeleteResolver", "appsync:CreateFunction", "appsync:DeleteFunction", "appsync:FlushApiCache", "appsync:CreateApiCache", "appsync:DeleteApiCache", "appsync:EvaluateCode", "appsync:EvaluateMappingTemplate", "appsync:GetGraphqlApiEnvironmentVariables", "appsync:PutGraphqlApiEnvironmentVariables", "appsync:TagResource", "appsync:UntagResource", "appsync:ListTagsForResource", "appsync:CreateDomainName", "appsync:DeleteDomainName", "appsync:GetDomainName", "appsync:ListDomainNames", "appsync:AssociateApi", "appsync:DisassociateApi", "appsync:GetApiAssociation" ], "Resource": "*" }, { "Sid": "CloudFormation", "Effect": "Allow", "Action": [ "cloudformation:CreateStack", "cloudformation:UpdateStack", "cloudformation:DeleteStack", "cloudformation:DescribeStacks", "cloudformation:DescribeStackResources", "cloudformation:DescribeStackEvents", "cloudformation:GetTemplate", "cloudformation:ListStacks", "cloudformation:ValidateTemplate", "cloudformation:CreateChangeSet", "cloudformation:DescribeChangeSet", "cloudformation:ExecuteChangeSet", "cloudformation:DeleteChangeSet" ], "Resource": "*" }, { "Sid": "Logs", "Effect": "Allow", "Action": [ "logs:FilterLogEvents", "logs:CreateLogGroup", "logs:DeleteLogGroup", "logs:PutRetentionPolicy", "logs:DescribeLogGroups", "logs:TagResource" ], "Resource": "*" }, { "Sid": "IamForDeploy", "Effect": "Allow", "Action": [ "iam:CreateRole", "iam:DeleteRole", "iam:GetRole", "iam:PassRole", "iam:PutRolePolicy", "iam:DeleteRolePolicy", "iam:AttachRolePolicy", "iam:DetachRolePolicy", "iam:TagRole" ], "Resource": "*" }, { "Sid": "DeploymentBucket", "Effect": "Allow", "Action": [ "s3:CreateBucket", "s3:DeleteBucket", "s3:ListBucket", "s3:GetObject", "s3:PutObject", "s3:DeleteObject", "s3:PutBucketPolicy", "s3:GetBucketPolicy", "s3:PutBucketTagging", "s3:GetEncryptionConfiguration", "s3:PutEncryptionConfiguration" ], "Resource": "*" }, { "Sid": "DomainTierOnly", "Effect": "Allow", "Action": [ "acm:ListCertificates", "route53:ListHostedZonesByName", "route53:ChangeResourceRecordSets", "route53:GetChange" ], "Resource": "*" }, { "Sid": "Identity", "Effect": "Allow", "Action": ["sts:GetCallerIdentity"], "Resource": "*" } ] }If you skip the custom-domain tier (the default), the
DomainTierOnlystatementand the domain-related AppSync actions are unnecessary.
Serverless v4 note
The suite spawns the
serverlessbinary fromnode_modules(override withSERVERLESS_BIN), so it can be pointed at a Serverless v4 install. Two caveats,unverified here:
SERVERLESS_ACCESS_KEY/ a license and suppression of loginprompts (the wrappers already disable telemetry and interactive setup).
getPromise/expireTimebranch in the plugin'sresolveCredentialswill not fire (itdegrades gracefully). Re-confirm the credential/region proof under v4.
Summary by CodeRabbit
Tests
Documentation
Chores