Skip to content

fix(deploy): make deploy.sh idempotent and document troubleshooting - #9

Merged
prathamesh-sonpatki merged 4 commits into
mainfrom
fix-deploy-idempotent-and-troubleshooting
Apr 30, 2026
Merged

prathamesh-sonpatki merged 4 commits into
mainfrom
fix-deploy-idempotent-and-troubleshooting

Conversation

@prathamesh-sonpatki

@prathamesh-sonpatki prathamesh-sonpatki commented Apr 30, 2026 •

Copy link
Copy Markdown
Member

Summary

Customer rollouts surfaced two latent bugs in deploy.sh and a docs gap.

1. IAM policy not reapplied on existing roles

put-role-policy was inside the if ! get-role branch, so it only ran on initial role creation. When PR #5 added ce:GetDimensionValues to the policy JSON, customers re-running ./deploy.sh against an existing role didn't get the new permission. Lambda then hit:

AccessDeniedException: User: ... is not authorized to perform: ce:GetDimensionValues

put-role-policy and attach-role-policy are idempotent — moved outside the branch so deploy.sh self-heals after permission changes.

2. ResourceConflictException on back-to-back updates

update-function-code is async — update-function-configuration immediately after races with the in-flight code update:

ResourceConflictException: An update is in progress for resource: arn:aws:lambda:...

Added aws lambda wait function-updated before each update call. Also waits before update-function-code itself (handles rerun-after-crash) and after create-function (newly created Lambdas start in Pending; add-permission requires Active).

3. Troubleshooting docs

Added a Troubleshooting section to aws-cost-explorer/README.md covering all four errors hit during rollouts: missing CE IAM perms, in-flight Lambda update, stale GroupBy 3-dim build, the old mktemp zip failure. Also clarified that AWS_REGION is an env var override (some users edited the script directly).

4. Hardening folded in from #7 + #8 (Closes #7, Closes #8)

  • trap-based temp file cleanup (zip + env file)
  • selective ResourceConflictException handling on add-permission so unrelated failures surface
  • RUNTIME override env var
  • JSON env vars via python json.dumps — fixes shorthand breakage when any value contains = or , (OTLP tokens, comma-bearing service names)
  • SMOKE_TEST=1 opt-in post-deploy invoke that fails on FunctionError

Closes #7
Closes #8

Test plan

  • ./deploy.sh on a fresh account creates role + policy + Lambda
  • ./deploy.sh re-run against existing role re-applies the inline policy (verify with aws iam get-role-policy --role-name aws-cost-reporter-role --policy-name cost-explorer-read)
  • Two back-to-back ./deploy.sh runs no longer hit ResourceConflictException
  • OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic <token-with-=>" survives round-trip into Lambda env (no shorthand breakage)
  • SMOKE_TEST=1 ./deploy.sh fails the script when IAM/OTLP misconfigured

prathamesh-sonpatki and others added 4 commits April 30, 2026 11:58
…perms

Previously put-role-policy only ran on initial role creation. Customers
re-running deploy.sh after a new code release (e.g., PR #5 added
ce:GetDimensionValues) hit AccessDeniedException at runtime because the
existing role wasn't patched.

put-role-policy and attach-role-policy are idempotent — always reapply.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
deploy.sh:
  Add `aws lambda wait function-updated` before and between
  update-function-code / update-function-configuration calls. Without
  these waits, back-to-back deploys hit ResourceConflictException
  ("An update is in progress for resource: ...").

README:
  Add Troubleshooting section covering the four errors seen in customer
  rollouts: missing CE IAM permissions, in-flight Lambda update conflict,
  stale GroupBy 3-dim build, and the old mktemp zip failure. Also
  clarify that AWS_REGION controls Lambda placement only — Cost
  Explorer is global — so users override it via env var rather than
  editing the script.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Drop pre-update wait (defensive, no prior async mutation in this path)
- Drop trailing wait after update-function-configuration (EventBridge
  put-rule/put-targets don't read Lambda update state)
- Keep the wait between update-function-code and update-function-configuration
  (the actual race that caused ResourceConflictException)
- ROLE_CREATED flag → simpler NEW_ROLE empty/non-empty test
- Trim narrating comments

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…test

Integrates hardening from #7 + #8 into the idempotent deploy work:
- trap-based temp file cleanup (BUILD_DIR, ZIP_PATH, ENV_FILE)
- wait function-updated before update-function-code (handles in-flight
  state from a prior crashed/concurrent run)
- wait function-active after create-function (newly created Lambdas
  start in Pending; add-permission requires Active)
- selective ResourceConflictException handling on add-permission so
  unrelated failures (regional, IAM, throttling) surface instead of
  being swallowed by `2>/dev/null || true`
- RUNTIME override (default python3.13) on both create-function and
  update-function-configuration
- JSON env vars via python json.dumps — fixes shorthand breakage when
  any value contains '=' or ',' (Last9 OTLP tokens, comma-bearing
  service names)
- SMOKE_TEST=1 opt-in post-deploy lambda invoke that fails the script
  on FunctionError. Default 0 to avoid spurious data points on every
  deploy during initial setup.

Co-Authored-By: karthikeyangs9 <174431822+karthikeyangs9@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@prathamesh-sonpatki
prathamesh-sonpatki merged commit 65b6452 into main Apr 30, 2026
4 checks passed
@prathamesh-sonpatki
prathamesh-sonpatki deleted the fix-deploy-idempotent-and-troubleshooting branch April 30, 2026 09:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant