@cyc-seattle/platform 1.0.0 → 1.2.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/README.md +16 -16
- package/dist/kubernetes.d.ts +1 -1
- package/dist/kubernetes.js +1 -1
- package/dist/outputs.js +3 -3
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -6,19 +6,19 @@ app owns. The apps that run on it live in their own repos, such as
|
|
|
6
6
|
|
|
7
7
|
## Stacks
|
|
8
8
|
|
|
9
|
-
| Stack | Holds
|
|
10
|
-
| ------------------------------- |
|
|
11
|
-
| [`bootstrap`](stacks/bootstrap) | Service accounts and project IAM, the Pulumi state buckets and KMS keys, and the org's GitHub repos and settings
|
|
12
|
-
| [`
|
|
13
|
-
| [`
|
|
14
|
-
| [`
|
|
9
|
+
| Stack | Holds | Applied by |
|
|
10
|
+
| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
|
11
|
+
| [`bootstrap`](stacks/bootstrap) | Service accounts and project IAM, the Pulumi state buckets and KMS keys, and the org's GitHub repos and settings | A human with project Owner and `gh` `admin:org`. Never CI. |
|
|
12
|
+
| [`infra`](stacks/infra) | The VPC, the cluster subnet and its Cloud NAT on a static address, the private services peering, the prod and dev Cloud SQL instances, the DNS zones, Artifact Registry, the GKE Autopilot cluster, the shared Gateway, its address, certificates, and dev's DNS records, the `dev` and `prod` namespaces with their quotas and network policies, dev's RBAC, the prod Job alerts, and each environment's `platform/outputs.json` | `deploy-runner`, from Actions after approval. A deployer, with `mise run deploy`, when breaking glass. |
|
|
13
|
+
| [`smoke`](stacks/smoke) | One `WebService` in dev, at `smoke.dev.cycsail.team`, for the integration tests | `deploy-dev`, from Actions on every PR. A deployer, with `PULUMI_STACK=dev mise run deploy`, when breaking glass. |
|
|
14
|
+
| [`backend`](stacks/backend) | Directus, with the schema apply from `schemas/`, its roles, policies, and permission rules, the sync machine users, its OIDC client, and MCP | `deploy-dev`, from Actions on every PR. Dev only, until prod cuts over (cyc-seattle/workplace#6 step 6). |
|
|
15
15
|
|
|
16
16
|
## @cyc-seattle/platform
|
|
17
17
|
|
|
18
18
|
`src/` is the `@cyc-seattle/platform` package, which the stacks here and the apps' stacks import:
|
|
19
19
|
|
|
20
20
|
- `getPlatformOutputs()` reads an environment's `platform/outputs.json` from its state bucket. The
|
|
21
|
-
`
|
|
21
|
+
`infra` stack writes it. It holds the environment's namespace and domain, the Gateway and its
|
|
22
22
|
address (`gatewayAddress`, for an app's own DNS records), and the Cloud SQL instance's connection
|
|
23
23
|
name and private IP (`sqlHost`). Dev stacks can't read prod's backend, so this replaces a
|
|
24
24
|
StackReference for platform values (cyc-seattle/isthmia#215).
|
|
@@ -56,19 +56,19 @@ two syncs as CronJobs) run in both, and dev adds Mailpit and the Clubspot and Wo
|
|
|
56
56
|
|
|
57
57
|
Each namespace denies ingress from other namespaces except the load balancer's. Dev also admits the
|
|
58
58
|
Kubernetes API's service proxy, which the integration tests use, and denies egress to the mail ports
|
|
59
|
-
(25, 465, 587) outside the cluster. `
|
|
59
|
+
(25, 465, 587) outside the cluster. `infra` writes dev's A records; each prod app writes its own,
|
|
60
60
|
pointing at `gatewayAddress`.
|
|
61
61
|
|
|
62
62
|
`deploy-dev` reads Secret Manager secrets whose IDs start with `dev-`. Read them with
|
|
63
63
|
`gcp.secretmanager.getSecretVersionAccess`, which needs only the accessor role.
|
|
64
64
|
|
|
65
|
-
`
|
|
66
|
-
`cyc-dev`, for each name in `
|
|
65
|
+
`infra` creates each app's dev database, user, and password secret (`dev-db-<name>-password`) on
|
|
66
|
+
`cyc-dev`, for each name in `infra:devDatabases`. To add an app's dev database, add its name there in a
|
|
67
67
|
platform PR: Cloud SQL ignores IAM conditions on its user and database calls, so `deploy-dev` can't
|
|
68
68
|
hold a role scoped to `cyc-dev`.
|
|
69
69
|
|
|
70
70
|
A Job that fails in `prod`, or a CronJob there with no successful Job in 3 hours, raises an alert.
|
|
71
|
-
It emails each address in `
|
|
71
|
+
It emails each address in `infra:alertEmails`, a secret in the stack's config, which holds the
|
|
72
72
|
maintainer's address (#20).
|
|
73
73
|
|
|
74
74
|
## Setup
|
|
@@ -100,11 +100,11 @@ GitHub environment that holds its identity and state bucket:
|
|
|
100
100
|
|
|
101
101
|
`prod-preview` runs `mise run preview` as `deploy-runner` and writes the diff to the job summary.
|
|
102
102
|
`prod` runs `mise run deploy` on the same commit once approved. It runs only when the preview shows
|
|
103
|
-
changes in `
|
|
103
|
+
changes in `infra`, so a merge that changes nothing in prod asks for no approval. A PR from a fork gets no OIDC token,
|
|
104
104
|
so its `dev` job is skipped.
|
|
105
105
|
|
|
106
|
-
`PULUMI_STACK` picks what the tasks run (`scripts/each-stack`): `dev` is `smoke`,
|
|
107
|
-
`
|
|
106
|
+
`PULUMI_STACK` picks what the tasks run (`scripts/each-stack`): `dev` is `smoke`, then `backend`, and
|
|
107
|
+
`prod` is `infra`. `integration` is dev only.
|
|
108
108
|
|
|
109
109
|
`bootstrap` is never deployed from Actions (cyc-seattle/isthmia#118). It holds the identities that
|
|
110
110
|
CI assumes, and a human with project Owner and `gh` `admin:org` applies it with the tasks below.
|
|
@@ -121,8 +121,8 @@ mise run deploy
|
|
|
121
121
|
PULUMI_STACK=dev mise run deploy
|
|
122
122
|
```
|
|
123
123
|
|
|
124
|
-
`mise run deploy` applies `
|
|
125
|
-
|
|
124
|
+
`mise run deploy` applies `infra`. isthmia's prod stacks read its outputs through a StackReference.
|
|
125
|
+
Dev stacks can't read prod state, so `infra` writes each environment's platform
|
|
126
126
|
values to `platform/outputs.json` in that environment's state bucket.
|
|
127
127
|
|
|
128
128
|
`bootstrap`'s GitHub provider uses `gh auth token`, so log `gh` in as a cyc-seattle org owner with
|
package/dist/kubernetes.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export interface ClusterProviderArgs {
|
|
|
11
11
|
/**
|
|
12
12
|
* A Kubernetes provider for the environment's cluster. Its kubeconfig runs gke-gcloud-auth-plugin
|
|
13
13
|
* with Application Default Credentials, so it is the same on every run, unlike one that embeds an
|
|
14
|
-
* access token. The plugin must be on PATH: `mise run install` adds it. The
|
|
14
|
+
* access token. The plugin must be on PATH: `mise run install` adds it. The infra stack passes
|
|
15
15
|
* only the endpoint, because it writes the rest.
|
|
16
16
|
*/
|
|
17
17
|
export declare function clusterProvider(platform: pulumi.Input<{
|
package/dist/kubernetes.js
CHANGED
|
@@ -3,7 +3,7 @@ import * as pulumi from "@pulumi/pulumi";
|
|
|
3
3
|
/**
|
|
4
4
|
* A Kubernetes provider for the environment's cluster. Its kubeconfig runs gke-gcloud-auth-plugin
|
|
5
5
|
* with Application Default Credentials, so it is the same on every run, unlike one that embeds an
|
|
6
|
-
* access token. The plugin must be on PATH: `mise run install` adds it. The
|
|
6
|
+
* access token. The plugin must be on PATH: `mise run install` adds it. The infra stack passes
|
|
7
7
|
* only the endpoint, because it writes the rest.
|
|
8
8
|
*/
|
|
9
9
|
export function clusterProvider(platform, name = "cluster", opts, args = {}) {
|
package/dist/outputs.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as gcp from "@pulumi/gcp";
|
|
2
2
|
import * as pulumi from "@pulumi/pulumi";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
-
// The
|
|
4
|
+
// The infra stack writes this object to each environment's state bucket, because a StackReference
|
|
5
5
|
// can't cross from a dev stack into prod's backend (cyc-seattle/isthmia#215).
|
|
6
6
|
export const platformOutputsSchema = z.object({
|
|
7
7
|
project: z.string().min(1),
|
|
@@ -49,10 +49,10 @@ export async function readPlatformOutputs(args = {}) {
|
|
|
49
49
|
({ content } = await gcp.storage.getBucketObjectContent({ bucket, name: outputsObject }));
|
|
50
50
|
}
|
|
51
51
|
catch (e) {
|
|
52
|
-
throw new Error(`Can't read ${source}. The
|
|
52
|
+
throw new Error(`Can't read ${source}. The infra stack writes it.\n${e.message}`);
|
|
53
53
|
}
|
|
54
54
|
if (!content) {
|
|
55
|
-
throw new Error(`${source} is empty. The
|
|
55
|
+
throw new Error(`${source} is empty. The infra stack writes it.`);
|
|
56
56
|
}
|
|
57
57
|
return parsePlatformOutputs(content, source);
|
|
58
58
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyc-seattle/platform",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Pulumi components for CYC's shared Google Cloud platform: WebService, the platform outputs reader, and the stacks that build the platform",
|
|
5
5
|
"author": "CYC Community Sailing Center",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
"@amiceli/vitest-cucumber": "7.0.0",
|
|
48
48
|
"@cyc-seattle/ts-config": "^0.1.2",
|
|
49
49
|
"@pulumi/command": "1.2.1",
|
|
50
|
+
"@pulumi/docker-build": "0.0.22",
|
|
50
51
|
"@pulumi/gcp": "10.2.0",
|
|
51
52
|
"@pulumi/github": "6.15.0",
|
|
52
53
|
"@pulumi/kubernetes": "4.34.2",
|