Skip to content

Auto-sync repos from GitHub teams, auto-generate TF boilerplate, drop CDK#69

Merged
Alexanderamiri merged 2 commits into
mainfrom
fix/dynamic-repo-registration
Mar 16, 2026
Merged

Auto-sync repos from GitHub teams, auto-generate TF boilerplate, drop CDK#69
Alexanderamiri merged 2 commits into
mainfrom
fix/dynamic-repo-registration

Conversation

@Alexanderamiri
Copy link
Copy Markdown
Member

Summary

  • Replace manual registered_app_repossync-registered-repos.py queries GitHub teams for repos and writes registered-apps.auto.tfvars. Runs pre-plan in platform CI. Manual trigger via workflow_dispatch.
  • Auto-generate backend.tf + providers.tfensure-tf-boilerplate.sh generates S3 backend and provider with default_tags (project, team, managed-by) for repos without app.yaml. Resolves team from GitHub API. Won't overwrite existing files.
  • Drop CDK — Remove has_cdk detection from detect.yml (not supported in pipeline)
  • Presentation docs — 7 markdown files covering the full platform for board presentation

Key design decisions

  • GitHub team membership is the source of truth for which repos get CI roles. No manual lists.
  • Auto-tagging via default_tags ensures all resources are tagged even without app.yaml. Combined with ABAC aws:RequestTag/project on the CI role, untagged resource creation is blocked.
  • Non-destructive boilerplate — existing backend.tf/providers.tf are never overwritten.

Test plan

  • Verify sync-registered-repos.py correctly lists repos from GitHub teams
  • Verify ensure-tf-boilerplate.sh generates correct backend.tf + providers.tf
  • Verify boilerplate is skipped when files already exist
  • Verify CDK detection removed from detect.yml
  • Run platform CI and confirm sync step runs before plan

… CDK

Registration:
- Add sync-registered-repos.py: queries GitHub teams for repos, writes
  registered-apps.auto.tfvars (replaces manual list)
- Platform CI runs sync before every plan + supports manual dispatch
- Add organization:read permission for GitHub team API access

App repo boilerplate:
- Add ensure-tf-boilerplate.sh: auto-generates backend.tf (S3 state)
  and providers.tf (with default_tags for project/team/managed-by)
  when repos don't have app.yaml
- Resolves team from GitHub API at CI runtime
- Won't overwrite existing files

CDK:
- Remove CDK detection from detect.yml (not supported in pipeline)
@Alexanderamiri Alexanderamiri force-pushed the fix/dynamic-repo-registration branch from 711c69a to 6ca2cfc Compare March 16, 2026 20:37
organization is not a valid GITHUB_TOKEN permission scope.
Also scope repo sync to main branch only (not needed on PRs).
@github-actions
Copy link
Copy Markdown

Terraform Plan

🚧 Changes detected — Plan: 4 to add, 0 to change, 0 to destroy.

Plan output

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # module.lambdas.aws_lambda_permission.password_set_alb will be created
  + resource "aws_lambda_permission" "password_set_alb" {
      + action              = "lambda:InvokeFunction"
      + function_name       = "javabin-password-set"
      + id                  = (known after apply)
      + principal           = "elasticloadbalancing.amazonaws.com"
      + source_arn          = (known after apply)
      + statement_id        = "AllowALBInvoke"
      + statement_id_prefix = (known after apply)
    }

  # module.lambdas.aws_lb_listener_rule.password_set will be created
  + resource "aws_lb_listener_rule" "password_set" {
      + arn          = (known after apply)
      + id           = (known after apply)
      + listener_arn = "arn:aws:elasticloadbalancing:eu-central-1:553637109631:listener/app/javabin-platform-alb/bec1dd43ab8341b9/500c9c2b4186bf45"
      + priority     = 10
      + tags_all     = {
          + "environment" = "production"
          + "managed-by"  = "terraform"
          + "project"     = "javabin"
          + "team"        = "javabin"
        }

      + action {
          + order            = (known after apply)
          + target_group_arn = (known after apply)
          + type             = "forward"
        }

      + condition {
          + host_header {
              + values = [
                  + "password.javazone.no",
                ]
            }
        }
    }

  # module.lambdas.aws_lb_target_group.password_set will be created
  + resource "aws_lb_target_group" "password_set" {
      + arn                                = (known after apply)
      + arn_suffix                         = (known after apply)
      + connection_termination             = (known after apply)
      + deregistration_delay               = "300"
      + id                                 = (known after apply)
      + ip_address_type                    = (known after apply)
      + lambda_multi_value_headers_enabled = false
      + load_balancer_arns                 = (known after apply)
      + load_balancing_algorithm_type      = (known after apply)
      + load_balancing_anomaly_mitigation  = (known after apply)
      + load_balancing_cross_zone_enabled  = (known after apply)
      + name                               = "javabin-password-set"
      + name_prefix                        = (known after apply)
      + preserve_client_ip                 = (known after apply)
      + protocol_version                   = (known after apply)
      + proxy_protocol_v2                  = false
      + slow_start                         = 0
      + tags_all                           = {
          + "environment" = "production"
          + "managed-by"  = "terraform"
          + "project"     = "javabin"
          + "team"        = "javabin"
        }
      + target_type                        = "lambda"

      + health_check {
          + enabled             = false
          + healthy_threshold   = 3
          + interval            = 30
          + matcher             = (known after apply)
          + path                = (known after apply)
          + port                = "traffic-port"
          + protocol            = "HTTP"
          + timeout             = (known after apply)
          + unhealthy_threshold = 3
        }
    }

  # module.lambdas.aws_lb_target_group_attachment.password_set will be created
  + resource "aws_lb_target_group_attachment" "password_set" {
      + id               = (known after apply)
      + target_group_arn = (known after apply)
      + target_id        = "arn:aws:lambda:eu-central-1:553637109631:function:javabin-password-set"
    }

Plan: 4 to add, 0 to change, 0 to destroy.

─────────────────────────────────────────────────────────────────────────────

Saved the plan to: tfplan

To perform exactly these actions, run the following command to apply:
    terraform apply "tfplan"

LLM Review

Risk: 🟢 LOW

Adding ALB integration for the password-set Lambda function via a new listener rule, target group, and permissions.

  • [routine] Creating ALB listener rule for password.javazone.no with priority 10, routing to new Lambda target group. Standard ALB configuration with no security concerns.
  • [routine] Adding Lambda target group for password-set function with health checks disabled (appropriate for Lambda). No unusual configuration detected.
  • [routine] Granting elasticloadbalancing.amazonaws.com principal permission to invoke the password-set Lambda function. Scoped to ALB service, not overly permissive.
  • [routine] No resources being destroyed or modified. Only 4 new resources being created for ALB integration.
  • [routine] Password-set Lambda already had public access via function URL and direct public invoke permissions. ALB routing adds an additional access path but doesn't increase exposure.

@Alexanderamiri Alexanderamiri merged commit a7411f7 into main Mar 16, 2026
3 checks passed
@Alexanderamiri Alexanderamiri deleted the fix/dynamic-repo-registration branch March 16, 2026 20:44
Alexanderamiri added a commit that referenced this pull request May 9, 2026
… CDK (#69)

## Summary
- **Replace manual `registered_app_repos`** — `sync-registered-repos.py`
queries GitHub teams for repos and writes `registered-apps.auto.tfvars`.
Runs pre-plan in platform CI. Manual trigger via `workflow_dispatch`.
- **Auto-generate backend.tf + providers.tf** —
`ensure-tf-boilerplate.sh` generates S3 backend and provider with
`default_tags` (project, team, managed-by) for repos without app.yaml.
Resolves team from GitHub API. Won't overwrite existing files.
- **Drop CDK** — Remove `has_cdk` detection from `detect.yml` (not
supported in pipeline)
- **Presentation docs** — 7 markdown files covering the full platform
for board presentation

## Key design decisions
- **GitHub team membership is the source of truth** for which repos get
CI roles. No manual lists.
- **Auto-tagging via `default_tags`** ensures all resources are tagged
even without app.yaml. Combined with ABAC `aws:RequestTag/project` on
the CI role, untagged resource creation is blocked.
- **Non-destructive boilerplate** — existing backend.tf/providers.tf are
never overwritten.

## Test plan
- [ ] Verify `sync-registered-repos.py` correctly lists repos from
GitHub teams
- [ ] Verify `ensure-tf-boilerplate.sh` generates correct backend.tf +
providers.tf
- [ ] Verify boilerplate is skipped when files already exist
- [ ] Verify CDK detection removed from detect.yml
- [ ] Run platform CI and confirm sync step runs before plan
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