@grada-run/grada 0.0.1 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/deploy-docs.yml +37 -0
- package/.github/workflows/e2e.yml +73 -0
- package/.github/workflows/iac-validation.yml +303 -0
- package/.github/workflows/publish.yml +68 -0
- package/.github/workflows/sync-bedrock-models.yml +57 -0
- package/.github/workflows/test.yml +43 -0
- package/.muserules +31 -0
- package/LICENSE +21 -0
- package/README.md +193 -3
- package/apps/docs/.astro/collections/docs.schema.json +644 -0
- package/apps/docs/.astro/content-assets.mjs +4 -0
- package/apps/docs/.astro/content-modules.mjs +4 -0
- package/apps/docs/.astro/content.d.ts +179 -0
- package/apps/docs/.astro/data-store.json +1 -0
- package/apps/docs/.astro/dev.json +14 -0
- package/apps/docs/.astro/settings.json +5 -0
- package/apps/docs/.astro/types.d.ts +2 -0
- package/apps/docs/astro.config.mjs +97 -0
- package/apps/docs/package.json +17 -0
- package/apps/docs/src/content/docs/adrs/0001-s3-native-state-locking.md +37 -0
- package/apps/docs/src/content/docs/adrs/0002-eject-mechanism-pure-iac.md +39 -0
- package/apps/docs/src/content/docs/adrs/0003-sync-ai-context-strategy.md +48 -0
- package/apps/docs/src/content/docs/adrs/0004-iac-driven-diagnostic-context.md +37 -0
- package/apps/docs/src/content/docs/adrs/0005-ecs-fargate-alb-runtime-target.md +38 -0
- package/apps/docs/src/content/docs/adrs/0006-github-oidc-no-stored-keys.md +37 -0
- package/apps/docs/src/content/docs/adrs/0007-framework-detection-with-fallback.md +37 -0
- package/apps/docs/src/content/docs/adrs/0008-secrets-names-in-git-values-in-aws.md +37 -0
- package/apps/docs/src/content/docs/adrs/0009-regenerate-with-backup-on-rerun.md +37 -0
- package/apps/docs/src/content/docs/adrs/0010-advisory-only-security-scans.md +37 -0
- package/apps/docs/src/content/docs/cli/add.md +85 -0
- package/apps/docs/src/content/docs/cli/apply.md +35 -0
- package/apps/docs/src/content/docs/cli/db.md +200 -0
- package/apps/docs/src/content/docs/cli/destroy.md +35 -0
- package/apps/docs/src/content/docs/cli/diagnose.md +37 -0
- package/apps/docs/src/content/docs/cli/doctor.md +28 -0
- package/apps/docs/src/content/docs/cli/domain.md +57 -0
- package/apps/docs/src/content/docs/cli/drift.md +40 -0
- package/apps/docs/src/content/docs/cli/eject.md +33 -0
- package/apps/docs/src/content/docs/cli/exec.md +49 -0
- package/apps/docs/src/content/docs/cli/gc.md +37 -0
- package/apps/docs/src/content/docs/cli/init.md +72 -0
- package/apps/docs/src/content/docs/cli/logs.md +39 -0
- package/apps/docs/src/content/docs/cli/rollback.md +51 -0
- package/apps/docs/src/content/docs/cli/secrets.md +73 -0
- package/apps/docs/src/content/docs/cli/sleep.md +53 -0
- package/apps/docs/src/content/docs/cli/status.md +34 -0
- package/apps/docs/src/content/docs/cli/sync-ai.md +27 -0
- package/apps/docs/src/content/docs/guides/architecture.md +87 -0
- package/apps/docs/src/content/docs/guides/aws-credentials.md +72 -0
- package/apps/docs/src/content/docs/guides/background-workers.md +45 -0
- package/apps/docs/src/content/docs/guides/cicd-pipeline.md +64 -0
- package/apps/docs/src/content/docs/guides/database-connections.md +64 -0
- package/apps/docs/src/content/docs/guides/docker-compose.md +37 -0
- package/apps/docs/src/content/docs/guides/dockerfiles.md +46 -0
- package/apps/docs/src/content/docs/guides/ephemeral-pr-previews.md +39 -0
- package/apps/docs/src/content/docs/guides/examples.md +50 -0
- package/apps/docs/src/content/docs/guides/frameworks.md +88 -0
- package/apps/docs/src/content/docs/guides/headless.md +87 -0
- package/apps/docs/src/content/docs/guides/quickstart.md +52 -0
- package/apps/docs/src/content/docs/guides/rerun-init.md +43 -0
- package/apps/docs/src/content/docs/guides/secrets-management.md +83 -0
- package/apps/docs/src/content/docs/guides/understanding-your-bill.md +63 -0
- package/apps/docs/src/content/docs/index.mdx +103 -0
- package/apps/docs/src/content/docs/migrations/astro-vercel-to-aws.md +55 -0
- package/apps/docs/src/content/docs/migrations/heroku-procfile-to-aws.md +41 -0
- package/apps/docs/src/content/docs/migrations/nextjs-vercel-to-aws.md +51 -0
- package/apps/docs/src/content/docs/migrations/sveltekit-vercel-to-aws.md +63 -0
- package/apps/docs/src/content/docs/roadmap.md +99 -0
- package/apps/docs/src/content/docs/testing-strategy.md +37 -0
- package/apps/docs/src/content.config.ts +7 -0
- package/apps/docs/src/custom.css +14 -0
- package/apps/docs/tsconfig.json +6 -0
- package/bin/cli.js +140 -0
- package/package.json +107 -7
- package/scripts/sync-bedrock-models.js +22 -0
- package/scripts/test-iac.js +261 -0
- package/specs/add-redis-sqs-bedrock.md +128 -0
- package/specs/add-storage-dynamodb.md +106 -0
- package/specs/bedrock-model-catalog.md +131 -0
- package/specs/ci-pipeline.md +17 -0
- package/specs/cost-transparency.md +115 -0
- package/specs/custom-domains-and-ses.md +153 -0
- package/specs/database-suite-expansion.md +151 -0
- package/specs/db-connect.md +69 -0
- package/specs/db-lifecycle-migrations.md +159 -0
- package/specs/dependency-aware-init.md +176 -0
- package/specs/deployment-safety.md +170 -0
- package/specs/diagnose.md +16 -0
- package/specs/docs-hub.md +16 -0
- package/specs/dx-polish.md +46 -0
- package/specs/e2e-testing.md +50 -0
- package/specs/exec.md +25 -0
- package/specs/finops-cron-drift.md +161 -0
- package/specs/gc.md +26 -0
- package/specs/integration-suite.md +16 -0
- package/specs/logs.md +32 -0
- package/specs/rollback-live-polling.md +40 -0
- package/specs/secrets-pull-audit.md +51 -0
- package/specs/serverless-lambda-target.md +133 -0
- package/specs/status.md +31 -0
- package/specs/telemetry-and-spawn-hardening.md +69 -0
- package/specs/telemetry-hardening.md +35 -0
- package/specs/test-suite-deduplication.md +42 -0
- package/src/commands/add.js +1111 -0
- package/src/commands/apply.js +214 -0
- package/src/commands/db/backup.js +229 -0
- package/src/commands/db/connect.js +304 -0
- package/src/commands/db/enable-vector.js +344 -0
- package/src/commands/db/import.js +604 -0
- package/src/commands/db/migrate.js +477 -0
- package/src/commands/db/restore.js +361 -0
- package/src/commands/db.js +87 -0
- package/src/commands/destroy.js +217 -0
- package/src/commands/diagnose.js +460 -0
- package/src/commands/doctor.js +109 -0
- package/src/commands/domain.js +685 -0
- package/src/commands/drift.js +243 -0
- package/src/commands/eject.js +130 -0
- package/src/commands/exec.js +222 -0
- package/src/commands/gc.js +250 -0
- package/src/commands/init.js +649 -0
- package/src/commands/logs.js +256 -0
- package/src/commands/rollback.js +323 -0
- package/src/commands/secrets.js +485 -0
- package/src/commands/sleep.js +347 -0
- package/src/commands/status.js +309 -0
- package/src/commands/sync-ai.js +115 -0
- package/src/commands/wake.js +337 -0
- package/src/core/parser.js +128 -0
- package/src/core/telemetry.js +244 -0
- package/src/data/bedrock-models.json +896 -0
- package/src/utils/addons.js +126 -0
- package/src/utils/ai-rules.js +59 -0
- package/src/utils/args.js +91 -0
- package/src/utils/aws.js +178 -0
- package/src/utils/backup.js +69 -0
- package/src/utils/bedrock-catalog.js +511 -0
- package/src/utils/capabilities.js +500 -0
- package/src/utils/command.js +78 -0
- package/src/utils/db-tunnel.js +164 -0
- package/src/utils/detector.js +298 -0
- package/src/utils/dockerCompose.js +65 -0
- package/src/utils/domains.js +73 -0
- package/src/utils/ecs-runner.js +289 -0
- package/src/utils/ecs.js +92 -0
- package/src/utils/frameworks.js +55 -0
- package/src/utils/generator.js +527 -0
- package/src/utils/hcl.js +426 -0
- package/src/utils/lambda-ecr.js +185 -0
- package/src/utils/prompts.js +278 -0
- package/src/utils/rds.js +131 -0
- package/src/utils/resolvers.js +174 -0
- package/src/utils/sleep-state.js +140 -0
- package/src/utils/sleep-targets.js +139 -0
- package/src/utils/system.js +42 -0
- package/src/utils/terraform.js +70 -0
- package/src/utils/visualizer.js +381 -0
- package/src/utils/warnings.js +49 -0
- package/templates/README.md +150 -0
- package/templates/docker/django.Dockerfile +40 -0
- package/templates/docker/go.Dockerfile +23 -0
- package/templates/docker/nestjs.Dockerfile +33 -0
- package/templates/docker/nextjs.Dockerfile +55 -0
- package/templates/docker/node.Dockerfile +24 -0
- package/templates/docker/nuxt.Dockerfile +47 -0
- package/templates/docker/python.Dockerfile +38 -0
- package/templates/docker/rails.Dockerfile +59 -0
- package/templates/docker/static.Dockerfile +32 -0
- package/templates/docker/svelte.Dockerfile +52 -0
- package/templates/github/deploy-lambda.yml +120 -0
- package/templates/github/deploy.yml +138 -0
- package/templates/github/drift.yml +112 -0
- package/templates/github/preview-lambda.yml +86 -0
- package/templates/github/preview.yml +69 -0
- package/templates/github/teardown.yml +43 -0
- package/templates/terraform/addons/bedrock.tf +34 -0
- package/templates/terraform/addons/cron-lambda.tf +78 -0
- package/templates/terraform/addons/cron.tf +101 -0
- package/templates/terraform/addons/dynamodb.tf +73 -0
- package/templates/terraform/addons/redis.tf +64 -0
- package/templates/terraform/addons/s3.tf +143 -0
- package/templates/terraform/addons/ses.tf +73 -0
- package/templates/terraform/addons/sqs.tf +67 -0
- package/templates/terraform/backend.tf +22 -0
- package/templates/terraform/cloudfront-lambda.tf +80 -0
- package/templates/terraform/cloudfront.tf +80 -0
- package/templates/terraform/database-aurora-postgresql.tf +92 -0
- package/templates/terraform/database-mysql.tf +72 -0
- package/templates/terraform/database.tf +71 -0
- package/templates/terraform/main-lambda.tf +229 -0
- package/templates/terraform/main.tf +296 -0
- package/templates/terraform/network.tf +95 -0
- package/templates/terraform/oidc.tf +64 -0
- package/templates/terraform/secrets.tf +31 -0
- package/templates/terraform/worker.tf +69 -0
- package/tests/__snapshots__/generator.test.js.snap +9633 -0
- package/tests/add.test.js +2018 -0
- package/tests/ai.test.js +91 -0
- package/tests/apply.test.js +446 -0
- package/tests/args.test.js +86 -0
- package/tests/aws.test.js +244 -0
- package/tests/capabilities.test.js +304 -0
- package/tests/cli.test.js +29 -0
- package/tests/command.test.js +99 -0
- package/tests/commands-import.test.js +74 -0
- package/tests/db.test.js +2673 -0
- package/tests/destroy.test.js +365 -0
- package/tests/detector.test.js +79 -0
- package/tests/diagnose.test.js +765 -0
- package/tests/doctor.test.js +195 -0
- package/tests/domain.test.js +882 -0
- package/tests/drift.test.js +228 -0
- package/tests/e2e/helpers.js +122 -0
- package/tests/e2e/tier0.e2e.test.js +142 -0
- package/tests/e2e/tier1.live.e2e.test.js +118 -0
- package/tests/ecs.test.js +130 -0
- package/tests/eject.test.js +65 -0
- package/tests/exec.test.js +366 -0
- package/tests/gc.test.js +466 -0
- package/tests/generator.test.js +794 -0
- package/tests/headless.test.js +491 -0
- package/tests/helpers/clack.js +103 -0
- package/tests/helpers/console.js +41 -0
- package/tests/helpers/telemetry.js +37 -0
- package/tests/helpers/tmpdir.js +36 -0
- package/tests/lambda-ecr.test.js +185 -0
- package/tests/logs.test.js +436 -0
- package/tests/parser.test.js +160 -0
- package/tests/rds.test.js +244 -0
- package/tests/resolvers.test.js +279 -0
- package/tests/rollback.test.js +670 -0
- package/tests/secrets.test.js +729 -0
- package/tests/sleep-wake.test.js +998 -0
- package/tests/status.test.js +356 -0
- package/tests/system.test.js +70 -0
- package/tests/telemetry.test.js +520 -0
- package/tests/terraform.test.js +84 -0
- package/tests/visualizer.test.js +480 -0
- package/vitest.config.js +10 -0
- package/vitest.e2e.tier0.config.js +8 -0
- package/vitest.e2e.tier1.config.js +8 -0
- package/index.js +0 -2
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Fetch GitHub's OIDC certificate thumbprint
|
|
2
|
+
data "tls_certificate" "github" {
|
|
3
|
+
url = "https://token.actions.githubusercontent.com"
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
variable "create_oidc_provider" {
|
|
7
|
+
description = "Set to false if you already have OIDC provider in your AWS account"
|
|
8
|
+
type = bool
|
|
9
|
+
default = true
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
# Register GitHub as an Identity Provider in AWS (Production Only)
|
|
13
|
+
resource "aws_iam_openid_connect_provider" "github" {
|
|
14
|
+
count = (var.create_oidc_provider && terraform.workspace == "default") ? 1 : 0
|
|
15
|
+
url = "https://token.actions.githubusercontent.com"
|
|
16
|
+
client_id_list = ["sts.amazonaws.com"]
|
|
17
|
+
thumbprint_list = [data.tls_certificate.github.certificates[0].sha1_fingerprint]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
# Reference the Provider (whether newly created or already existing)
|
|
21
|
+
data "aws_iam_openid_connect_provider" "github_existing" {
|
|
22
|
+
count = (var.create_oidc_provider && terraform.workspace == "default") ? 0 : 1
|
|
23
|
+
url = "https://token.actions.githubusercontent.com"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
# Dynamically pick the ARN of the provider based on the variable
|
|
27
|
+
locals {
|
|
28
|
+
github_provider_arn = (var.create_oidc_provider && terraform.workspace == "default") ? aws_iam_openid_connect_provider.github[0].arn : data.aws_iam_openid_connect_provider.github_existing[0].arn
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
# Create the IAM Role that GitHub Actions will assume
|
|
32
|
+
resource "aws_iam_role" "github_actions" {
|
|
33
|
+
count = terraform.workspace == "default" ? 1 : 0
|
|
34
|
+
name = "{{PROJECT_NAME}}-github-actions-role"
|
|
35
|
+
|
|
36
|
+
assume_role_policy = jsonencode({
|
|
37
|
+
Version = "2012-10-17"
|
|
38
|
+
Statement = [
|
|
39
|
+
{
|
|
40
|
+
Action = "sts:AssumeRoleWithWebIdentity"
|
|
41
|
+
Effect = "Allow"
|
|
42
|
+
Principal = {
|
|
43
|
+
Federated = local.github_provider_arn
|
|
44
|
+
}
|
|
45
|
+
Condition = {
|
|
46
|
+
StringLike = {
|
|
47
|
+
# ⚠️ SECURITY: Update "repo:*" to "repo:your-github-username/your-repo-name:*" in production
|
|
48
|
+
"token.actions.githubusercontent.com:sub" : "repo:*"
|
|
49
|
+
}
|
|
50
|
+
StringEquals = {
|
|
51
|
+
"token.actions.githubusercontent.com:aud" : "sts.amazonaws.com"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
# Grant the CI/CD pipeline permissions to provision infrastructure
|
|
60
|
+
resource "aws_iam_role_policy_attachment" "github_actions_admin" {
|
|
61
|
+
count = terraform.workspace == "default" ? 1 : 0
|
|
62
|
+
role = aws_iam_role.github_actions[0].name
|
|
63
|
+
policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
|
|
64
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# --- Shared AWS Secrets Manager ---
|
|
2
|
+
|
|
3
|
+
# 1. Only create the Secret Vault in the default (production) workspace
|
|
4
|
+
resource "aws_secretsmanager_secret" "app_secrets" {
|
|
5
|
+
count = terraform.workspace == "default" ? 1 : 0
|
|
6
|
+
name = "{{PROJECT_NAME}}-secrets"
|
|
7
|
+
description = "Environment variables for {{PROJECT_NAME}}"
|
|
8
|
+
recovery_window_in_days = 0 # Allows instant deletion for dev/POC environments
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
# 2. Fetch the existing Secret Vault when running in a PR workspace
|
|
12
|
+
data "aws_secretsmanager_secret" "existing_secrets" {
|
|
13
|
+
count = terraform.workspace != "default" ? 1 : 0
|
|
14
|
+
name = "{{PROJECT_NAME}}-secrets"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
# 3. Export a single local variable that works in both environments
|
|
18
|
+
locals {
|
|
19
|
+
secret_arn = terraform.workspace == "default" ? aws_secretsmanager_secret.app_secrets[0].arn : data.aws_secretsmanager_secret.existing_secrets[0].arn
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
# Initial placeholder secret so the ECS task doesn't fail on first boot
|
|
23
|
+
resource "aws_secretsmanager_secret_version" "app_secrets_initial" {
|
|
24
|
+
count = terraform.workspace == "default" ? 1 : 0
|
|
25
|
+
secret_id = aws_secretsmanager_secret.app_secrets[0].id
|
|
26
|
+
secret_string = jsonencode({{INITIAL_SECRET_MAP}})
|
|
27
|
+
|
|
28
|
+
lifecycle {
|
|
29
|
+
ignore_changes = [secret_string]
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# --- Worker ECS Task Definition ---
|
|
2
|
+
resource "aws_ecs_task_definition" "worker" {
|
|
3
|
+
family = "${local.app_name}-worker-task"
|
|
4
|
+
network_mode = "awsvpc"
|
|
5
|
+
requires_compatibilities = ["FARGATE"]
|
|
6
|
+
cpu = "{{CPU}}"
|
|
7
|
+
memory = "{{MEMORY}}"
|
|
8
|
+
execution_role_arn = aws_iam_role.execution_role.arn
|
|
9
|
+
task_role_arn = aws_iam_role.task_role.arn
|
|
10
|
+
|
|
11
|
+
container_definitions = jsonencode([
|
|
12
|
+
{
|
|
13
|
+
name = "${local.app_name}-worker-container"
|
|
14
|
+
image = "${local.ecr_url}:${terraform.workspace == "default" ? "latest" : terraform.workspace}"
|
|
15
|
+
essential = true
|
|
16
|
+
|
|
17
|
+
environment = [
|
|
18
|
+
{ "name": "NODE_ENV", "value": "production" },
|
|
19
|
+
{{DB_ENV_VARS}}
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
secrets = concat(
|
|
23
|
+
[
|
|
24
|
+
for key in local.secret_keys : {
|
|
25
|
+
name = key
|
|
26
|
+
valueFrom = "${local.secret_arn}:${key}::"
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
[
|
|
30
|
+
{{TASK_SECRETS}}
|
|
31
|
+
]
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
{{WORKER_COMMAND}}
|
|
35
|
+
|
|
36
|
+
logConfiguration = {
|
|
37
|
+
logDriver = "awslogs"
|
|
38
|
+
options = {
|
|
39
|
+
"awslogs-group" = aws_cloudwatch_log_group.app_logs.name
|
|
40
|
+
"awslogs-region" = "{{REGION}}"
|
|
41
|
+
"awslogs-stream-prefix" = "worker" # Isolates worker logs from web logs
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
])
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
# --- Worker ECS Service ---
|
|
49
|
+
# Notice there is NO load_balancer block. This service is strictly private.
|
|
50
|
+
resource "aws_ecs_service" "worker" {
|
|
51
|
+
name = "${local.app_name}-worker-service"
|
|
52
|
+
cluster = aws_ecs_cluster.main.id
|
|
53
|
+
task_definition = aws_ecs_task_definition.worker.arn
|
|
54
|
+
launch_type = "FARGATE"
|
|
55
|
+
desired_count = 1
|
|
56
|
+
enable_execute_command = true
|
|
57
|
+
|
|
58
|
+
network_configuration {
|
|
59
|
+
subnets = aws_subnet.public[*].id
|
|
60
|
+
security_groups = [aws_security_group.ecs_tasks.id]
|
|
61
|
+
assign_public_ip = true
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
# Queue-depth auto-scaling (see `grada add queue:sqs`) manages
|
|
65
|
+
# desired_count outside Terraform; ignore it to avoid apply-time drift.
|
|
66
|
+
lifecycle {
|
|
67
|
+
ignore_changes = [desired_count]
|
|
68
|
+
}
|
|
69
|
+
}
|