Skip to content

Add GitHub CI AWS bootstrap stack#60

Open
Kravalg wants to merge 35 commits into
codex/issue20-pulumi-escfrom
codex/issue59-github-ci-bootstrap-stack
Open

Add GitHub CI AWS bootstrap stack#60
Kravalg wants to merge 35 commits into
codex/issue20-pulumi-escfrom
codex/issue59-github-ci-bootstrap-stack

Conversation

@Kravalg

@Kravalg Kravalg commented May 25, 2026

Copy link
Copy Markdown
Contributor

Pull Request

Description

Adds a separate one-time Pulumi project at pulumi/github-ci-bootstrap for bootstrapping AWS-only GitHub CI access without Pulumi Cloud or Pulumi ESC.

The stack creates/adopts the GitHub OIDC provider, fixed AWS Secrets Manager CI config containers, one config-read role per CI suffix, dedicated preview/apply/drift roles, and the test-account operations alert triage role. By default it writes the non-static-credential CI JSON payloads into Secrets Manager as encrypted Pulumi secret values.

Related Issue

Closes #59. Stacked on #57 because it reuses the AWS Secrets Manager CI loader and config components introduced there.

Motivation and Context

PR #57 is blocked because the GitHub Actions OIDC roles and CI config secrets do not exist in AWS yet. This PR provides the isolated admin-once bootstrap path so the normal CI roles can stay least-privilege instead of giving GitHub AdministratorAccess.

How Has This Been Tested?

  • uv run pytest tests/unit/test_components.py -q
  • uv run pytest tests/pulumi/test_project_structure.py tests/pulumi/test_delivery_contracts.py -q
  • uv run ruff check pulumi/infra/ci_bootstrap.py pulumi/infra/ci_config.py pulumi/github-ci-bootstrap/__main__.py tests/unit/test_components.py tests/pulumi/test_project_structure.py tests/pulumi/test_delivery_contracts.py
  • uv run ruff format --check pulumi/infra/ci_bootstrap.py pulumi/infra/ci_config.py pulumi/github-ci-bootstrap/__main__.py tests/unit/test_components.py tests/pulumi/test_project_structure.py tests/pulumi/test_delivery_contracts.py
  • uv run ty check pulumi/github-ci-bootstrap/__main__.py
  • make test-yaml
  • make test-actionlint
  • make test-secrets
  • git diff --check

Screenshots (if appropriate)

N/A

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

  • My code follows the code style of this project.
  • I have performed a self-review of my code.
  • I have commented my code, particularly in hard-to-understand areas.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING.md document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • You have only one commit (if not, squash them into one commit).

Summary by cubic

Adds a standalone Pulumi project at pulumi/github-ci-bootstrap to bootstrap AWS-only GitHub CI without Pulumi Cloud/ESC and routes PR deployment commands to that project. Tightens GitHub OIDC trust to the repository subject plus allowed workflow names and refreshes Well‑Architected evidence.

  • New Features

    • Bootstrap stack: creates/adopts the GitHub OIDC provider, fixed AWS Secrets Manager CI containers, per-suffix config-read roles, per-env GitHubCiPreview-*, GitHubCiApply-*, GitHubCiDrift-*, and test OperationsAlertTriage-*; writes CI JSON payloads by default (toggle github-ci-bootstrap:writeSecretValues); optional Pulumi backend/secrets provider; resource protection/import via github-ci-bootstrap:protectResources; CiConfiguration now takes CiConfigurationArgs and exports created secrets.
    • Trust and guardrails: locks OIDC to the repository subject and known workflow names via the supported workflow claim, with an explicit workflow-ref allowlist fallback; includes environment:test trust; validates managed policy sizes; policy pack allowlists bootstrap/test wildcard IAM managed policies.
    • CI and tooling: PR command runner targets pulumi/github-ci-bootstrap via PULUMI_DIR with safe path validation; Pulumi plan manifest paths must stay under the repo; non‑prod decrypt/lock fallback retries a guarded direct apply without policy checks; rotates AWS CI config payloads; relaxes self-check merge-state; AWS docs verifier sends request headers; env validator checks PULUMI_DIR; Dockerfile verifies Pulumi/AWS CLIs and pulumi_aws; adds pulumi-aws>=7,<8.
    • Permissions, tests, and evidence: apply allows Pulumi backend/ECR/Secrets Manager metadata (incl. S3 accelerate config); drift allows cost-allocation reads; tests cover path-escape cases, PR runner matrices, and Pulumi state bucket refresh; refreshes Well‑Architected 5‑of‑5 evidence to 2026‑06‑07 and updates the test-account security attestation to an approved exception; docs added, including the bootstrap stack guide.
  • Migration

    • Run once locally for test and prod with admin AWS profiles: pulumi -C pulumi/github-ci-bootstrap up --stack <stack>.
    • Capture outputs and set repo variables from githubVariables; verify role ARNs, secret IDs, and secret version IDs.
    • If secret writes are disabled or a repair is needed, use aws secretsmanager put-secret-value.

Written for commit 5dfcc08. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

Release Notes

  • New Features

    • Added GitHub Actions OIDC integration with AWS, enabling secure CI workflows to authenticate without long-lived credentials.
    • Introduced AWS Secrets Manager configuration for CI payloads with automated secret handling.
  • Documentation

    • Added comprehensive guides for GitHub Actions AWS bootstrap setup and configuration.
    • Updated AWS Secrets Manager documentation with bootstrap stack integration details.
  • Chores

    • Added test coverage and validation specifications for new CI bootstrap functionality.
    • Added architecture and implementation documentation for GitHub Actions AWS integration.

Review Change Stack

@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR implements Issue #59: a one-time Pulumi bootstrap stack that operators run locally to provision GitHub OIDC provider, CI configuration read roles, deployment roles (preview/apply/drift), operations triage role, and AWS Secrets Manager CI payloads. The bootstrap stack is isolated from normal CI runs and uses AWS-only backend/secrets, eliminating Pulumi Cloud/ESC dependency for privileged CI infrastructure setup.

Changes

GitHub CI Bootstrap Stack

Layer / File(s) Summary
CI Configuration Args Contract and Wiring
pulumi/infra/ci_config.py, pulumi/infra/bootstrap_infrastructure.py, pulumi/infra/__init__.py
CiConfigurationArgs dataclass centralizes settings and optional oidc_provider_arn/protect_resources; CiConfiguration.__init__ updated to accept args instead of separate parameters; resource protection threaded through Secret/Role/RolePolicy creation options.
Bootstrap Stack Project Configuration
pulumi/github-ci-bootstrap/Pulumi.yaml, pulumi/github-ci-bootstrap/Pulumi.test.yaml, pulumi/github-ci-bootstrap/Pulumi.prod.yaml, pulumi/github-ci-bootstrap/Pulumi.example.yaml, pulumi/github-ci-bootstrap/requirements.txt
Establishes isolated pulumi/github-ci-bootstrap Python project with stack-specific YAML configs (region, GitHub org/branch, cost center, classification, secrets provider, service naming, writeSecretValues); delegates dependency resolution to parent requirements.
AWS Provider Dependency
pulumi/requirements.txt
Adds pulumi-aws>=7.0,<8 to support IAM OIDC provider, role, policy, and Secrets Manager operations.
Core GitHubCiBootstrap Component
pulumi/infra/ci_bootstrap.py
Implements Pulumi component with deterministic role naming (preview/apply/drift/triage), OIDC trust policies parameterized by GitHub org/repo/branch/environment/workflow-refs, IAM policy builders for read-only preview/drift vs. full apply permissions, operations triage role/policy (test-only), JSON secret payload generation with Pulumi backend/KMS details, and optional Secrets Manager version creation; exports component outputs (OIDC ARN, secret IDs/read-role ARNs, deployment role ARNs, triage role ARN, GitHub variables, payload keys, secret version IDs).
Bootstrap Stack Entrypoint and Exports
pulumi/github-ci-bootstrap/__main__.py, pulumi/infra/__init__.py
Entrypoint reads Pulumi config, builds BootstrapSettings, instantiates GitHubCiBootstrap, and exports stack outputs; module __init__.py exports GitHubCiBootstrap, GitHubCiBootstrapArgs, and CiConfigurationArgs.
Operational Setup Documentation
docs/github-ci-bootstrap-stack.md, docs/aws-secrets-manager-ci-cutover.md, docs/github-actions-secrets.md
github-ci-bootstrap-stack.md provides runbook: fix AWS CLI profile inheritance, perform local Pulumi login/preview/up for test and prod with shared S3 backend and AWS KMS secrets provider, capture stack outputs, set GitHub repository variables, manage secret payloads using secretsmanager put-secret-value; integration docs clarify bootstrap stack role and default payload write behavior.
Architecture and Specification
specs/issue-59-github-ci-aws-bootstrap/architecture.md, specs/issue-59-github-ci-aws-bootstrap/prd.md, specs/issue-59-github-ci-aws-bootstrap/epics.md, specs/issue-59-github-ci-aws-bootstrap/implementation-readiness-report.md
Documents design: control boundaries (local admin vs. GitHub OIDC), tech stack (Pulumi Python, IAM/OIDC, Secrets Manager, S3 backend, KMS), bootstrap contract, OIDC trust constraints, IAM permission inventory, Secrets Manager payload contract, and requirements/epics with acceptance criteria; readiness report covers design decisions, validation plan, and manual apply blockers.
Comprehensive Test Coverage
tests/unit/test_components.py, tests/pulumi/test_project_structure.py, tests/pulumi/test_delivery_contracts.py
Adds helper for consistent bootstrap settings; updates CiConfiguration tests to use CiConfigurationArgs; introduces tests covering GitHubCiBootstrap role/trust/payload behavior for test and prod stacks (including protected apply subject, secret value presence/absence, error paths); validates bootstrap project isolation, non-secret stack configs, and OIDC reference in entrypoint; updates delivery contract test to include bootstrap documentation.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

  • #20: Both changes address AWS-only CI setup by moving CI configuration from GitHub secrets to AWS Secrets Manager and OIDC-backed roles.

Possibly related PRs

Suggested labels

enhancement, documentation, ci, aws, pulumi, needs-admin

Suggested reviewers

  • dmytrocraft

Poem

🐰 A bootstrap stack hops into town,

OIDC trust roles handed down,

No Cloud needed, S3 stays near,

CI secrets encrypted, crystal clear! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.47% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'Add GitHub CI AWS bootstrap stack' accurately summarizes the main change: adding a new isolated bootstrap stack for GitHub CI AWS resources.
Linked Issues check ✅ Passed The changes comprehensively address all objectives from issue #59: isolated bootstrap stack, OIDC provider, secrets manager containers, least-privilege roles, tight OIDC trust policies, documentation, and tests validating stack and trust scopes.
Out of Scope Changes check ✅ Passed All changes are scoped to GitHub CI AWS bootstrap: new bootstrap stack implementation, docs, tests, config files, and updates to existing components to support the bootstrap feature. No unrelated changes detected.
Description check ✅ Passed PR description is comprehensive and well-structured, covering motivation, testing, and all required checklist items with clear answers.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/issue59-github-ci-bootstrap-stack

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@qltysh

qltysh Bot commented May 25, 2026

Copy link
Copy Markdown

1 new issue

Tool Category Rule Count
qlty Duplication Found 20 lines of similar code in 3 locations (mass = 76) 1

Comment thread pulumi/infra/ci_bootstrap.py Outdated
Comment thread pulumi/infra/ci_bootstrap.py Outdated
Comment thread pulumi/infra/ci_bootstrap.py Outdated
Comment thread pulumi/infra/ci_bootstrap.py Outdated
Comment thread pulumi/infra/ci_bootstrap.py Outdated
Comment thread pulumi/infra/ci_bootstrap.py Outdated
Comment thread pulumi/infra/ci_bootstrap.py Outdated
Comment thread pulumi/infra/ci_bootstrap.py
Comment thread pulumi/infra/ci_config.py

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

2 issues found across 15 files

Confidence score: 2/5

  • There is a concrete high-impact dependency gap in pulumi/github-ci-bootstrap/requirements.txt: pulumi_aws is required via the infra module but not installed, which is likely to cause bootstrap/runtime failures.
  • docs/github-ci-bootstrap-stack.md includes a shell expansion timing issue where ${PULUMI_BACKEND_URL} will not use the inline temporary assignment, so documented setup commands may fail for users following the guide.
  • Given the high severity/high confidence of the missing package issue (8/10, 8/10), this looks risky to merge until corrected.
  • Pay close attention to pulumi/github-ci-bootstrap/requirements.txt and docs/github-ci-bootstrap-stack.md - dependency installation and backend login command behavior need validation.
Architecture diagram
sequenceDiagram
    participant Admin as Admin (local CLI)
    participant Pulumi as Pulumi CLI (github-ci-bootstrap)
    participant AWS as AWS Account
    participant OIDC as GitHub OIDC Provider
    participant SM as Secrets Manager
    participant IAM as IAM Roles
    
    Note over Admin,IAM: NEW: One-time bootstrap flow (no Pulumi Cloud/ESC)
    
    Admin->>Pulumi: pulumi up (admin AWS profile)
    Pulumi->>AWS: aws sts get-caller-identity (verify account)
    AWS-->>Pulumi: Account 891377212104 (test) / 933245420672 (prod)
    
    Pulumi->>OIDC: Create/Adopt OIDC provider for token.actions.githubusercontent.com
    OIDC-->>Pulumi: OIDC provider ARN
    
    Pulumi->>SM: Create secret containers (/bootstrap-infrastructure/ci/{suffix})
    SM-->>Pulumi: Secret ARN/ID
    
    alt writeSecretValues enabled (default)
        Pulumi->>SM: Write encrypted CI JSON payloads (role ARNs, backend URL, etc.)
        SM-->>Pulumi: Secret version ID
    else writeSecretValues disabled
        Note over Pulumi,SM: Manual put-secret-value later
    end
    
    Pulumi->>IAM: Create GitHubCiConfigRead-{suffix} role (trust: OIDC + repo subject + workflow)
    Pulumi->>IAM: Create GitHubCiPreview-{env} role (read-only, no Secrets Manager Get)
    Pulumi->>IAM: Create GitHubCiApply-{env} role (mutation, no AdministratorAccess)
    Pulumi->>IAM: Create GitHubCiDrift-{env} role (same as preview)
    
    alt environment == "test"
        Pulumi->>IAM: Create OperationsAlertTriage-{env} role (SQS only)
        IAM-->>Pulumi: Operations alert triage role ARN
    end
    
    IAM-->>Pulumi: All role ARNs
    
    Pulumi-->>Admin: Stack outputs (githubVariables, role ARNs, secret IDs)
    
    Note over Admin,Pulumi: Post-apply: capture and set GitHub variables
    
    Admin->>Admin: Set GitHub repo variables from githubVariables output
    
    Note over Admin,IAM: Normal CI usage (separate flow)
    participant GH as GitHub Actions (later)
    
    GH->>OIDC: Request token with job_workflow_ref + repo subject
    OIDC-->>GH: JWT (aud: sts.amazonaws.com)
    
    GH->>IAM: Assume GitHubCiConfigRead-{suffix} role
    alt subject matches + workflow ref matches
        IAM-->>GH: Temp credentials (read secret only)
        GH->>SM: GetSecretValue (CI config payload)
        SM-->>GH: JSON with deployment role ARNs
        GH->>IAM: Assume GitHubCiPreview/Apply/Drift-{env} role
        alt subject matches + workflow ref matches
            IAM-->>GH: Temp credentials (scoped permissions)
        else mismatch
            IAM-->>GH: Access denied
        end
    else mismatch
        IAM-->>GH: Access denied
    end
Loading

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread pulumi/github-ci-bootstrap/requirements.txt
Comment thread docs/github-ci-bootstrap-stack.md Outdated
@dmytrocraft dmytrocraft force-pushed the codex/issue59-github-ci-bootstrap-stack branch 2 times, most recently from c07aa14 to ceac5f8 Compare May 25, 2026 17:47
Comment thread pulumi/infra/ci_bootstrap.py Outdated
Comment thread pulumi/infra/ci_bootstrap.py Outdated
Comment thread pulumi/infra/ci_bootstrap.py Outdated
Comment thread pulumi/infra/ci_bootstrap.py Outdated
Comment thread tests/unit/test_components.py Outdated
@dmytrocraft dmytrocraft force-pushed the codex/issue59-github-ci-bootstrap-stack branch from ceac5f8 to 157ff21 Compare May 25, 2026 19:49
@Kravalg

Kravalg commented May 25, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@dmytrocraft dmytrocraft force-pushed the codex/issue59-github-ci-bootstrap-stack branch from 157ff21 to 7b0e7e8 Compare May 25, 2026 19:57
@Kravalg

Kravalg commented May 25, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Kravalg

Kravalg commented May 25, 2026

Copy link
Copy Markdown
Contributor Author

Status update for Issue 59 bootstrap PR:

  • Added BMAD specs under specs/issue-59-github-ci-aws-bootstrap/ with PRD, architecture, epics, and readiness report.
  • Completed the local BMALPH flow and recorded sanitized evidence in the specs.
  • Fixed the current qlty and Cubic findings, including the direct pulumi-aws>=7.0,<8 bootstrap requirement and the shell login command issue.
  • CodeRabbit approval is present, qlty check/fmt are green, and there are no unresolved current review threads.

Current head: 7b0e7e8.

CI status: all repo-fixable checks are green. The only failing checks are Preview and Test Account Evidence; both fail while assuming arn:aws:iam::891377212104:role/GitHubCiConfigRead-bootstrap-infrastructure-test-pr with GitHub OIDC. That is the expected external blocker until the one-time AWS bootstrap stack is manually applied in the AWS accounts and the privileged checks are rerun.

Comment thread pulumi/infra/ci_config.py Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

0 issues found across 2 files (changes from recent commits).

Re-trigger cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1 issue found across 5 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread pulumi/infra/ci_bootstrap.py

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

0 issues found across 3 files (changes from recent commits).

Requires human review: Auto-approval blocked by 1 unresolved issue from previous reviews.

Re-trigger cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1 issue found across 2 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread pulumi/infra/ci_config.py Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1 issue found across 1 file (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread Dockerfile Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

0 issues found across 4 files (changes from recent commits).

Re-trigger cubic

@cubic-dev-ai

cubic-dev-ai Bot commented Jun 7, 2026

Copy link
Copy Markdown

You're iterating quickly on this pull request. To help protect your rate limits, cubic has paused automatic reviews on new pushes for now—when you're ready for another review, comment @cubic-dev-ai review.

Comment thread tests/pulumi/test_ci_guardrails.py Outdated
Comment thread tests/pulumi/test_ci_guardrails.py Outdated
Comment thread scripts/run_pulumi_command.py
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.

2 participants