diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index d73ee1b..a5e275c 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,9 +1,19 @@ name: Deploy on: push: - branches: [main, master] + branches: [main] pull_request: + workflow_dispatch: + +permissions: + id-token: write # AWS access via OIDC + contents: write # platform commits generated Terraform to the branch + pull-requests: write # plan + review comment on PRs + +# No secrets needed — see +# https://github.com/javaBin/platform/blob/main/docs/reusable-workflows.md jobs: javabin: + # The template repo itself never deploys; repos created from it do. + if: github.repository != 'javaBin/app-template' uses: javaBin/platform/.github/workflows/javabin.yml@main - secrets: inherit diff --git a/CLAUDE.md b/CLAUDE.md index d49b01c..aecebd4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -15,19 +15,21 @@ GitHub template repository for creating new services on the Javabin platform. 1. Click **"Use this template"** on GitHub to create a new repo under `javaBin/` 2. Edit `app.yaml` — set your service name, team, compute settings, routing, and any resources -3. Ensure your team is registered in [javaBin/registry](https://github.com/javaBin/registry) (`teams/{name}.yaml`) and add the repo to your GitHub team +3. Ensure your team is registered in [javaBin/registry](https://github.com/javaBin/registry) (`teams/{name}.yaml`) and add the repo to the GitHub team named in `app.yaml` `team:` (CI verifies repo → team before vending credentials) 4. Push to `main` — the platform CI builds, plans, reviews, and deploys automatically +5. Set any secret values: `brew install javaBin/tap/javabin`, `javabin aws setup` (SSO permission set `javabin-team-`), then `javabin secret set ` ## app.yaml Fields - `name` — service name (required, lowercase + hyphens, max 20 chars) -- `team` — owning team, must exist in the registry (required) -- `compute` — CPU, memory, port, desired count, health check path +- `team` — owning team, lowercase letters only (max 12), must exist in the registry (required) +- `compute` — CPU, memory, port, desired count, health check path, `user` (default `"1000"`), `readonly_root_filesystem` (default `true`; only `/tmp` writable) - `routing` — hostname under `javazone.no` and ALB priority -- `resources` — S3 buckets, DynamoDB tables, Secrets Manager secrets, SQS queues -- `auth` — Cognito integration: `internal`, `external`, `both`, or `none` +- `resources` — S3 buckets, DynamoDB tables / RDS PostgreSQL, SSM secrets (created as `PLACEHOLDER`, set with `javabin secret set`), SQS queues +- `auth` — Cognito: `internal`/`external` shorthand, or full form with `client: confidential|public|none`, `callback_urls` (https or `http://localhost`), `groups` (restricts sign-in), `env` (alias injected names) - `environment` — custom environment variables -- `budget_alert_nok` — monthly budget alert threshold in NOK + +Unknown fields fail the pipeline's `expand` step. Budgets are per team, set in the registry. Full reference: [app.yaml reference](https://github.com/javaBin/platform/blob/main/docs/app-yaml-reference.md) @@ -37,10 +39,13 @@ The default Dockerfile uses `eclipse-temurin:21` for a Java/Maven project. Repla ## CI -This template includes `.github/workflows/deploy.yml` which calls the platform's reusable workflow `javaBin/platform/.github/workflows/javabin.yml@main`. No additional workflow config needed. +This template includes `.github/workflows/deploy.yml` which calls the platform's reusable workflow `javaBin/platform/.github/workflows/javabin.yml@main`. No secrets are needed; keep the `permissions:` block (`id-token: write`, `contents: write`, `pull-requests: write`). The job's `if: github.repository != 'javaBin/app-template'` keeps the template itself from deploying; generated repos have another name, so it runs there. + +Validate `app.yaml` locally against the generator from a platform checkout: +`GITHUB_WORKSPACE=. APP_SERVICE=my-service AWS_ACCOUNT_ID=553637109631 TF_ROOT=/tmp/gen python3 -I ../platform/scripts/generate-modules.py` ## Related - [javaBin/platform](https://github.com/javaBin/platform) — shared infrastructure and reusable modules - [javaBin/registry](https://github.com/javaBin/registry) — team registration -- [javaBin/javabin-cli](https://github.com/javaBin/javabin-cli) — `javabin register` automates team registration +- [javaBin/javabin-cli](https://github.com/javaBin/javabin-cli) — `javabin register-team`, `javabin aws setup`, `javabin secret set` diff --git a/README.md b/README.md index 147728f..6987895 100644 --- a/README.md +++ b/README.md @@ -4,21 +4,39 @@ A Javabin platform service. ## Getting Started -1. **Create from template**: Click "Use this template" on GitHub -2. **Register your team**: If not already registered, open a PR to [javaBin/registry](https://github.com/javaBin/registry) adding `teams/your-team.yaml`, then add this repo to your GitHub team -3. **Customize `app.yaml`**: Set your service name, team, compute, and routing -4. **Push to main**: The platform CI pipeline builds, plans, reviews, and deploys automatically +1. **Create from template**: Click "Use this template" on GitHub (repo under `javaBin/`) +2. **Register your team**: If not already registered, open a PR to [javaBin/registry](https://github.com/javaBin/registry) adding `teams/.yaml` (or run `javabin register-team`). Merging creates the GitHub team and the team's AWS CI roles; members sign in to AWS with the SSO permission set `javabin-team-`. Team names are lowercase letters only, max 12 chars. +3. **Add this repo to your GitHub team** — the one named in `app.yaml` `team:`; CI refuses to deploy otherwise: + `gh api -X PUT orgs/javaBin/teams//repos/javaBin/ -f permission=push` +4. **Customize `app.yaml`**: Set your service name, team, compute, routing, and any resources/auth +5. **Push to main**: The platform CI pipeline builds, plans, reviews, and deploys automatically. Pull requests get a Terraform plan and review comment. + +No repository secrets are needed. `.github/workflows/deploy.yml` must keep its `permissions:` block (`id-token: write`, `contents: write`, `pull-requests: write`). Its `if:` only stops the template repo itself from deploying; it is true in your repo. + +## Secrets + +`resources.secrets` entries are created with the value `PLACEHOLDER` on the first deploy. Set real values with the [javabin CLI](https://github.com/javaBin/javabin-cli) from this repo: + +```bash +brew install javaBin/tap/javabin +javabin aws setup # SSO sign-in with javabin-team- +javabin secret list # which secrets still hold PLACEHOLDER +javabin secret set api-key # prompts without echo; --stdin to pipe +``` + +The service restarts automatically within a minute to pick up the new value. ## Platform Features - Automatic Docker build and ECR push -- Terraform infrastructure from `app.yaml` (S3, DynamoDB, SQS, Secrets Manager) +- Terraform infrastructure from `app.yaml` (S3, DynamoDB, RDS PostgreSQL, SQS, SSM secrets, Cognito clients) - LLM-powered plan review with risk gating -- ECS Fargate deployment with health checks -- CloudWatch alarms and cost monitoring +- ECS Fargate deployment with health checks and circuit-breaker rollback +- CloudWatch alarms; budgets per team (set in the registry) ## References - [app.yaml reference](https://github.com/javaBin/platform/blob/main/docs/app-yaml-reference.md) +- [Reusable workflows](https://github.com/javaBin/platform/blob/main/docs/reusable-workflows.md) - [Platform documentation](https://github.com/javaBin/platform) - [Registry](https://github.com/javaBin/registry) diff --git a/app.yaml b/app.yaml index 11e3339..6a7b1f8 100644 --- a/app.yaml +++ b/app.yaml @@ -1,21 +1,27 @@ # app.yaml — Javabin Platform Service Configuration # Full reference: https://github.com/javaBin/platform/blob/main/docs/app-yaml-reference.md +# +# Validated strictly: unknown or misspelled fields fail the pipeline's `expand` step. +# Budgets are not set here — they are per team (`budget_nok` in javaBin/registry teams/.yaml). -# Service name (required) — lowercase + hyphens, max 20 chars +# Service name — starts with a letter; lowercase letters, digits, hyphens; max 20 chars (default: repo name) name: my-service -# Owning team (required) — must match a team in javaBin/registry -team: my-team +# Owning team (required) — lowercase letters only, max 12 chars. Must exist in +# javaBin/registry (teams/.yaml), and this repo must be in that GitHub team. +team: myteam -# Container compute settings (optional, defaults shown) +# Container compute settings (optional; omitted fields use platform defaults) compute: cpu: 512 # vCPU units (256, 512, 1024, 2048, 4096) - memory: 1024 # MB (512-30720, must match cpu) - port: 8080 # container port your app listens on + memory: 1024 # MB, must be a valid Fargate combination with cpu + port: 8080 # container port your app listens on (platform default: 8000) desired_count: 1 # number of running tasks health_check: /health + # user: "1000" # container user (default "1000", non-root) + # readonly_root_filesystem: true # default true — only /tmp is writable; set false if the app writes elsewhere -# ALB routing (required for web services) +# ALB routing — omit for a worker with no load balancer routing: host: my-service.javazone.no # DNS name, must be under javazone.no priority: 100 # unique across all apps (1-50000) @@ -26,22 +32,31 @@ routing: # - name: data # env: DATA_BUCKET # databases: -# - name: cache +# - name: cache # DynamoDB (default) # hash_key: id # env: CACHE_TABLE -# secrets: -# - name: api-key +# - name: main # RDS PostgreSQL +# engine: postgres +# env: DATABASE_URL +# secrets: # created as PLACEHOLDER; set the value after the first deploy: +# - name: api-key # javabin aws setup && javabin secret set api-key # env: API_KEY # queues: # - name: jobs # env: JOBS_QUEUE_URL -# Cognito auth (optional) — internal, external, both, or none -# auth: internal +# Cognito auth (optional). Shorthand: `auth: internal` (Javabin heroes) or `auth: external` (public users). +# auth: +# pool: internal +# client: confidential # confidential (server-side login, id + secret) | public (browser PKCE, id only) | none (API that only verifies tokens) +# callback_urls: # default: https:/// and /auth/callback +# - https://my-service.javazone.no/auth/callback +# - http://localhost:8080/auth/callback # localhost allowed for local dev +# groups: # only members of these registry groups can sign in +# - team-myteam +# env: # also inject values under your own names +# COGNITO_CLIENT_ID: OIDC_CLIENT_ID # Custom environment variables # environment: # LOG_LEVEL: info - -# Monthly budget alert in NOK (default: 1000) -# budget_alert_nok: 500