Skip to content

Migrate CI/CD from CodePipeline to GitHub Actions#193

Merged
layertwo merged 1 commit into
mainlinefrom
migrate-to-github-actions
Feb 24, 2026
Merged

Migrate CI/CD from CodePipeline to GitHub Actions#193
layertwo merged 1 commit into
mainlinefrom
migrate-to-github-actions

Conversation

@layertwo

@layertwo layertwo commented Feb 12, 2026

Copy link
Copy Markdown
Owner

Summary

Replace AWS CodePipeline with GitHub Actions workflows for CI/CD. Replace Smithy CLI binary download with Smithy Gradle Plugin for reproducible, version-managed builds. Remove Beta stage and simplify to single Prod deployment.

  • Add GitHub Actions workflows for deploy, frontend build, lambda tests, code review, code scan, and CodeQL
  • Add Gradle project in smithy/ with smithy-jar plugin (v1.3.0) to build Smithy models and generate OpenAPI specs
  • Move Smithy Maven dependencies from smithy-build.json to Gradle
  • Remove old CodePipeline stack (lib/stacks/pipeline.ts)
  • Remove Smithy CLI download URL and version constants from config
  • Remove Beta stage (BETA enum, Beta stacks, Beta deploy job, Beta/Prod RemovalPolicy conditionals)
  • Rename stacks to suffix pattern (ServiceStack-prod, MonitoringStack-prod)
  • Add cdk-diff workflow for PR diff comments via corymhall/cdk-diff-action@v2

Test plan

  • Verify cd smithy && ./gradlew smithyBuild produces OpenAPI specs at build/smithy/{storage,token}/openapi/
  • Verify cdk synth reads the generated specs successfully
  • Verify deploy workflow runs end-to-end in GitHub Actions
  • Verify Renovate picks up Gradle dependency versions
  • Verify cdk ls outputs ServiceStack-prod and MonitoringStack-prod
  • Verify cdk-diff workflow triggers on PRs touching lib/ or smithy/

Comment thread .github/workflows/deploy.yml Outdated
Comment thread .github/workflows/deploy.yml Outdated
aws-region: ${{ env.AWS_REGION }}

- name: Deploy Beta-ServiceStack
run: npx cdk deploy Beta-ServiceStack --app build/cdk.out --require-approval never

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LOW - Deployment Safety: No Rollback Strategy

The deployment steps use --require-approval never which bypasses CDK's safety checks. If a deployment fails midway, there's no automated rollback mechanism.

Recommendation: Consider:

  1. Adding --rollback flag support (available in newer CDK versions)
  2. Adding a post-deployment verification step
  3. Using --progress events for better visibility into deployment progress

Example:

- name: Deploy Beta-ServiceStack
  run: npx cdk deploy Beta-ServiceStack --app build/cdk.out --require-approval never --progress events

Comment thread .github/workflows/deploy.yml Outdated
Comment thread lib/config.ts Outdated
Comment thread lib/app.ts Outdated
Comment thread .github/workflows/deploy.yml Outdated
Comment thread .github/workflows/deploy.yml
Repository owner deleted a comment from claude Bot Feb 22, 2026
@layertwo layertwo force-pushed the migrate-to-github-actions branch 5 times, most recently from b2cb70e to cf1cd39 Compare February 24, 2026 00:22
@layertwo layertwo force-pushed the migrate-to-github-actions branch 2 times, most recently from a16677a to 89d39c0 Compare February 24, 2026 00:26
@layertwo layertwo force-pushed the migrate-to-github-actions branch from 89d39c0 to 20deb12 Compare February 24, 2026 01:56
@layertwo layertwo force-pushed the migrate-to-github-actions branch from 20deb12 to 96c448b Compare February 24, 2026 01:59
@layertwo layertwo force-pushed the migrate-to-github-actions branch from 96c448b to e238c49 Compare February 24, 2026 02:22
- Add GitHub Actions workflows for deploy, frontend build, lambda tests,
  code review, code scan, and CodeQL
- Add Gradle project in smithy/ with smithy-jar plugin (v1.3.0) to build
  Smithy models and generate OpenAPI specs
- Move Smithy Maven dependencies from smithy-build.json to Gradle
- Remove old CodePipeline stack (lib/stacks/pipeline.ts)
- Remove Smithy CLI download URL and version constants from config
- Remove Beta stage (BETA enum, Beta stacks, Beta deploy job, Beta/Prod
  RemovalPolicy conditionals) — simplify to single Prod deployment
- Rename stacks to suffix pattern (ServiceStack-prod, MonitoringStack-prod)
- Add cdk-diff workflow for PR diff comments via corymhall/cdk-diff-action
@github-actions

Copy link
Copy Markdown

Diff for stage: DefaultStage

Diff for stack: GitHubOidcStack - 0 to add, 1 to update, 0 to destroy 🟡

Details
Resources
[~] Custom::AWSCDKOpenIdConnectProvider GitHubOidcProvider7EBF861F
 └─ [~] CodeHash
     ├─ [-] 62fa02efcaa700e1c247e1d3cc2aa0cd07a0808a9a3e3d2230e51f57a02233fb
     └─ [+] d75c48c9f82cde63e9bf414df335e84e8ac24f11eb34889be255b702aec71e50
[~] AWS::Lambda::Function CustomAWSCDKOpenIdConnectProviderCustomResourceProviderHandlerF2C543E0
 ├─ [~] Code
 │   └─ [~] .S3Key:
 │       ├─ [-] 62fa02efcaa700e1c247e1d3cc2aa0cd07a0808a9a3e3d2230e51f57a02233fb.zip
 │       └─ [+] d75c48c9f82cde63e9bf414df335e84e8ac24f11eb34889be255b702aec71e50.zip
 └─ [~] Metadata
     └─ [~] .aws:asset:path:
         ├─ [-] asset.62fa02efcaa700e1c247e1d3cc2aa0cd07a0808a9a3e3d2230e51f57a02233fb
         └─ [+] asset.d75c48c9f82cde63e9bf414df335e84e8ac24f11eb34889be255b702aec71e50

Diff for stack: Service-prod - 37 to add, 0 to update, 0 to destroy ❇️

Details
IAM Statement Changes
┌───┬─────────────────────────────────────────────────┬────────┬───────────────────────────────┬─────────────────────────────────────────────────┬───────────┐
│   │ Resource                                        │ Effect │ Action                        │ Principal                                       │ Condition │
├───┼─────────────────────────────────────────────────┼────────┼───────────────────────────────┼─────────────────────────────────────────────────┼───────────┤
│ + │ ${ApiHandler5E7490E8.Arn}                       │ Allow  │ lambda:InvokeFunction         │ AWS:${ApiRole1873F438}                          │           │
│   │ ${ApiHandler5E7490E8.Arn}:*                     │        │                               │                                                 │           │
│   │ ${HawkAuthorizerHandlerAE21734A.Arn}            │        │                               │                                                 │           │
│   │ ${HawkAuthorizerHandlerAE21734A.Arn}:*          │        │                               │                                                 │           │
│   │ ${TokenApiHandler2E66DB25.Arn}                  │        │                               │                                                 │           │
│   │ ${TokenApiHandler2E66DB25.Arn}:*                │        │                               │                                                 │           │
├───┼─────────────────────────────────────────────────┼────────┼───────────────────────────────┼─────────────────────────────────────────────────┼───────────┤
│ + │ ${ApiHandlerServiceRole592E70E9.Arn}            │ Allow  │ sts:AssumeRole                │ Service:lambda.amazonaws.com                    │           │
├───┼─────────────────────────────────────────────────┼────────┼───────────────────────────────┼─────────────────────────────────────────────────┼───────────┤
│ + │ ${ApiRole1873F438.Arn}                          │ Allow  │ sts:AssumeRole                │ Service:apigateway.amazonaws.com                │           │
├───┼─────────────────────────────────────────────────┼────────┼───────────────────────────────┼─────────────────────────────────────────────────┼───────────┤
│ + │ ${HawkAuthorizerHandlerServiceRoleBD62F31B.Arn} │ Allow  │ sts:AssumeRole                │ Service:lambda.amazonaws.com                    │           │
├───┼─────────────────────────────────────────────────┼────────┼───────────────────────────────┼─────────────────────────────────────────────────┼───────────┤
│ + │ ${OidcSecret99EA0351}                           │ Allow  │ secretsmanager:DescribeSecret │ AWS:${TokenApiHandlerServiceRoleF15460EF}       │           │
│   │                                                 │        │ secretsmanager:GetSecretValue │                                                 │           │
├───┼─────────────────────────────────────────────────┼────────┼───────────────────────────────┼─────────────────────────────────────────────────┼───────────┤
│ + │ ${StorageApiCloudWatchRole192C26DE.Arn}         │ Allow  │ sts:AssumeRole                │ Service:apigateway.amazonaws.com                │           │
├───┼─────────────────────────────────────────────────┼────────┼───────────────────────────────┼─────────────────────────────────────────────────┼───────────┤
│ + │ ${StorageTableF2BE222E.Arn}                     │ Allow  │ dynamodb:BatchGetItem         │ AWS:${ApiHandlerServiceRole592E70E9}            │           │
│   │ ${StorageTableF2BE222E.Arn}/index/*             │        │ dynamodb:BatchWriteItem       │                                                 │           │
│   │                                                 │        │ dynamodb:ConditionCheckItem   │                                                 │           │
│   │                                                 │        │ dynamodb:DeleteItem           │                                                 │           │
│   │                                                 │        │ dynamodb:DescribeTable        │                                                 │           │
│   │                                                 │        │ dynamodb:GetItem              │                                                 │           │
│   │                                                 │        │ dynamodb:GetRecords           │                                                 │           │
│   │                                                 │        │ dynamodb:GetShardIterator     │                                                 │           │
│   │                                                 │        │ dynamodb:PutItem              │                                                 │           │
│   │                                                 │        │ dynamodb:Query                │                                                 │           │
│   │                                                 │        │ dynamodb:Scan                 │                                                 │           │
│   │                                                 │        │ dynamodb:UpdateItem           │                                                 │           │
├───┼─────────────────────────────────────────────────┼────────┼───────────────────────────────┼─────────────────────────────────────────────────┼───────────┤
│ + │ ${TokenApiCloudWatchRole094666DE.Arn}           │ Allow  │ sts:AssumeRole                │ Service:apigateway.amazonaws.com                │           │
├───┼─────────────────────────────────────────────────┼────────┼───────────────────────────────┼─────────────────────────────────────────────────┼───────────┤
│ + │ ${TokenApiHandlerServiceRoleF15460EF.Arn}       │ Allow  │ sts:AssumeRole                │ Service:lambda.amazonaws.com                    │           │
├───┼─────────────────────────────────────────────────┼────────┼───────────────────────────────┼─────────────────────────────────────────────────┼───────────┤
│ + │ ${TokenCacheTable317DB082.Arn}                  │ Allow  │ dynamodb:BatchGetItem         │ AWS:${HawkAuthorizerHandlerServiceRoleBD62F31B} │           │
│   │                                                 │        │ dynamodb:ConditionCheckItem   │                                                 │           │
│   │                                                 │        │ dynamodb:DescribeTable        │                                                 │           │
│   │                                                 │        │ dynamodb:GetItem              │                                                 │           │
│   │                                                 │        │ dynamodb:GetRecords           │                                                 │           │
│   │                                                 │        │ dynamodb:GetShardIterator     │                                                 │           │
│   │                                                 │        │ dynamodb:Query                │                                                 │           │
│   │                                                 │        │ dynamodb:Scan                 │                                                 │           │
├───┼─────────────────────────────────────────────────┼────────┼───────────────────────────────┼─────────────────────────────────────────────────┼───────────┤
│ + │ ${TokenCacheTable317DB082.Arn}                  │ Allow  │ dynamodb:BatchGetItem         │ AWS:${TokenApiHandlerServiceRoleF15460EF}       │           │
│   │ ${TokenUsersTableAED6F12A.Arn}                  │        │ dynamodb:BatchWriteItem       │                                                 │           │
│   │                                                 │        │ dynamodb:ConditionCheckItem   │                                                 │           │
│   │                                                 │        │ dynamodb:DeleteItem           │                                                 │           │
│   │                                                 │        │ dynamodb:DescribeTable        │                                                 │           │
│   │                                                 │        │ dynamodb:GetItem              │                                                 │           │
│   │                                                 │        │ dynamodb:GetRecords           │                                                 │           │
│   │                                                 │        │ dynamodb:GetShardIterator     │                                                 │           │
│   │                                                 │        │ dynamodb:PutItem              │                                                 │           │
│   │                                                 │        │ dynamodb:Query                │                                                 │           │
│   │                                                 │        │ dynamodb:Scan                 │                                                 │           │
│   │                                                 │        │ dynamodb:UpdateItem           │                                                 │           │
└───┴─────────────────────────────────────────────────┴────────┴───────────────────────────────┴─────────────────────────────────────────────────┴───────────┘
IAM Policy Changes
┌───┬─────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────────────────────────────┐
│   │ Resource                                    │ Managed Policy ARN                                                                      │
├───┼─────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────┤
│ + │ ${ApiHandlerServiceRole592E70E9}            │ arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole          │
├───┼─────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────┤
│ + │ ${HawkAuthorizerHandlerServiceRoleBD62F31B} │ arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole          │
├───┼─────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────┤
│ + │ ${StorageApiCloudWatchRole192C26DE}         │ arn:${AWS::Partition}:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs │
├───┼─────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────┤
│ + │ ${TokenApiCloudWatchRole094666DE}           │ arn:${AWS::Partition}:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs │
├───┼─────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────┤
│ + │ ${TokenApiHandlerServiceRoleF15460EF}       │ arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole          │
└───┴─────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)

Parameters
[+] Parameter BootstrapVersion: {"Type":"AWS::SSM::Parameter::Value<String>","Default":"/cdk-bootstrap/hnb659fds/version","Description":"Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"}

Resources
[+] AWS::IAM::Role ApiRole1873F438
[+] AWS::IAM::Policy ApiRoleDefaultPolicyCFEBAD31
[+] AWS::DynamoDB::Table TokenUsersTableAED6F12A
[+] AWS::DynamoDB::Table TokenCacheTable317DB082
[+] AWS::DynamoDB::Table StorageTableF2BE222E
[+] AWS::IAM::Role HawkAuthorizerHandlerServiceRoleBD62F31B
[+] AWS::IAM::Policy HawkAuthorizerHandlerServiceRoleDefaultPolicy4948790F
[+] AWS::Lambda::Function HawkAuthorizerHandlerAE21734A
[+] AWS::SecretsManager::Secret OidcSecret99EA0351
[+] AWS::IAM::Role TokenApiHandlerServiceRoleF15460EF
[+] AWS::IAM::Policy TokenApiHandlerServiceRoleDefaultPolicy3580140F
[+] AWS::Lambda::Function TokenApiHandler2E66DB25
[+] AWS::IAM::Role ApiHandlerServiceRole592E70E9
[+] AWS::IAM::Policy ApiHandlerServiceRoleDefaultPolicy10321D87
[+] AWS::Lambda::Function ApiHandler5E7490E8
[+] AWS::CertificateManager::Certificate TokenCertificate45FDFF82
[+] AWS::Logs::LogGroup TokenApiGatewayAccessLogs5C430E2A
[+] AWS::ApiGateway::RestApi TokenApiA934D4AB
[+] AWS::IAM::Role TokenApiCloudWatchRole094666DE
[+] AWS::ApiGateway::Account TokenApiAccountE3C3A2E7
[+] AWS::ApiGateway::Deployment TokenApiDeploymentB896C219640115439fa3a7f0afb0ee5e6dfa0a14
[+] AWS::ApiGateway::Stage TokenApiDeploymentStageprod11035AE4
[+] AWS::ApiGateway::DomainName TokenApiCustomDomain9D366D9E
[+] AWS::ApiGateway::BasePathMapping TokenApiCustomDomainMapServiceprodTokenApiF278F89460B1A372
[+] AWS::Route53::RecordSet TokenARecordSetB7E7A96F
[+] AWS::Route53::RecordSet TokenAAAARecordSetE3797E09
[+] AWS::CertificateManager::Certificate StorageCertificate984AE68E
[+] AWS::Logs::LogGroup StorageApiGatewayAccessLogs910D88A3
[+] AWS::ApiGateway::RestApi StorageApiAD520CAE
[+] AWS::IAM::Role StorageApiCloudWatchRole192C26DE
[+] AWS::ApiGateway::Account StorageApiAccount8566DF75
[+] AWS::ApiGateway::Deployment StorageApiDeployment3B4929C5382a8526c0ee60374d77de6c755ec11e
[+] AWS::ApiGateway::Stage StorageApiDeploymentStageprodF84F218F
[+] AWS::ApiGateway::DomainName StorageApiCustomDomainFC4C7F21
[+] AWS::ApiGateway::BasePathMapping StorageApiCustomDomainMapServiceprodStorageApiC4965599B1AF06C2
[+] AWS::Route53::RecordSet StorageARecordSet857154E4
[+] AWS::Route53::RecordSet StorageAAAARecordSetA18AE9E5

Outputs
[+] Output ExportsOutputRefApiHandler5E7490E896301149: {"Value":{"Ref":"ApiHandler5E7490E8"},"Export":{"Name":"Service-prod:ExportsOutputRefApiHandler5E7490E896301149"}}
[+] Output ExportsOutputRefStorageTableF2BE222E2B650759: {"Value":{"Ref":"StorageTableF2BE222E"},"Export":{"Name":"Service-prod:ExportsOutputRefStorageTableF2BE222E2B650759"}}
[+] Output TokenApiEndpointFB0CB04E: {"Value":{"Fn::Join":["",["https://",{"Ref":"TokenApiA934D4AB"},".execute-api.us-west-2.",{"Ref":"AWS::URLSuffix"},"/",{"Ref":"TokenApiDeploymentStageprod11035AE4"},"/"]]}}
[+] Output StorageApiEndpoint5F7D3E16: {"Value":{"Fn::Join":["",["https://",{"Ref":"StorageApiAD520CAE"},".execute-api.us-west-2.",{"Ref":"AWS::URLSuffix"},"/",{"Ref":"StorageApiDeploymentStageprodF84F218F"},"/"]]}}

Diff for stack: Monitoring-prod - 1 to add, 0 to update, 0 to destroy ❇️

Details
Parameters
[+] Parameter BootstrapVersion: {"Type":"AWS::SSM::Parameter::Value<String>","Default":"/cdk-bootstrap/hnb659fds/version","Description":"Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"}

Resources
[+] AWS::CloudWatch::Dashboard FFSyncprodFFSyncprodDashboardsDashboardBF900E93

Generated for commit 044d439 at 2026-02-24T02:31:31.588Z

@layertwo layertwo merged commit 62fd506 into mainline Feb 24, 2026
6 checks passed
@layertwo layertwo deleted the migrate-to-github-actions branch February 24, 2026 02: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