Against a real account only the credentials change: the job trades a GitHub 29 OIDC token for a deployment role's temporary keys (Configuring OIDC Trust for AWS). The sub claim the trust policy matches depends on the repository's age: gh api repos/binarybehemoth/booknest-infra/actions/oidc/customization/sub reports the prefix repo:binarybehemoth@15277380/booknest-infra@1388136108. Created after 15 July 2026, the repository gets the immutable, ID-based subject, so a policy written for repo:binarybehemoth/booknest-infra:... would never match. Following AWS 24 's and GitHub's documentation:
production:
needs: deploy
runs-on: ubuntu-24.04
environment: production
permissions: {id-token: write, contents: read}
steps:
- uses: actions/checkout@v7 # then lint and package as above, to a real bucket
- uses: aws-actions/configure-aws-credentials@v6
with:
role-to-assume: arn:aws:iam::123456789012:role/booknest-infra-deploy
aws-region: us-east-1
- run: |
aws cloudformation deploy --stack-name booknest-api \
--template-file packaged.yaml --capabilities CAPABILITY_IAM \
--role-arn arn:aws:iam::123456789012:role/booknest-cfn-servicePin the trust policy's sub to repo:binarybehemoth@15277380/booknest-infra@1388136108:environment:production, so only approved production jobs, after a clean LocalStack 63,725 deploy, assume the role. It needs CloudFormation 24 access, the artifact bucket and iam:PassRole for the service role (Caller vs Service Role). To review first, create a change set in one job and execute it in another (Change Sets and Policies), for example with aws-actions/aws-cloudformation-github-deploy (2.2.0) in its create-only mode.