Skip to content

Commit

Permalink
Set up pulumi GCP and register an auth client for auth.zemn.me
Browse files Browse the repository at this point in the history
  • Loading branch information
Zemnmez committed Feb 25, 2025
1 parent 7e8e833 commit 32470a4
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 5 deletions.
29 changes: 27 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
---

name: CI
# yamllint disable rule:line-length
#

on: # yamllint disable-line rule:truthy
merge_group:
Expand Down Expand Up @@ -74,6 +76,8 @@ jobs:
env:
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
Staging:
permissions:
id-token: write
# Pulumi doesn't like it when multiple deploys are attempted at once.
# This is also enforced at the pulumi layer, but i'm sure github actions
# would make me pay while that thread waits to acquire the lock.
Expand Down Expand Up @@ -101,6 +105,13 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
ref: main
- uses: 'google-github-actions/auth@v2'
name: Acquire GCloud credentials for first deploy.
id: auth
with:
project_id: 'extreme-cycling-441523-a9'
workload_identity_provider: 'projects/845702659200/locations/global/workloadIdentityPools/github/providers/my-repo'
service_account: [email protected]
- name: Pulumi up from origin/main to staging
# dirty used here so the state transition is main -> candidate
# we test if the script exists so we don't fail as a result of it
Expand Down Expand Up @@ -128,6 +139,13 @@ jobs:
PERSONAL_PHONE_NUMBER: ${{ secrets.PERSONAL_PHONE_NUMBER }}
- name: Switch back to candidate branch
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- uses: 'google-github-actions/auth@v2'
name: Re-acquire GCloud credentials after checkout...
id: auth2
with:
project_id: 'extreme-cycling-441523-a9'
workload_identity_provider: 'projects/845702659200/locations/global/workloadIdentityPools/github/providers/my-repo'
service_account: [email protected]
- name: Deploy candidate branch to Staging
# we can run this dirty since the next run will --overwrite anyway
run: |
Expand All @@ -145,6 +163,8 @@ jobs:
TWILIO_AUTH_TOKEN: ${{ secrets.TWILIO_AUTH_TOKEN }}
PERSONAL_PHONE_NUMBER: ${{ secrets.PERSONAL_PHONE_NUMBER }}
Submit:
permissions:
id-token: write
concurrency: pulumi_production
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
# Attempts to submit changes to production.
Expand All @@ -161,8 +181,13 @@ jobs:
large-packages: false
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
# example copied from:
# https://github.com/actions/cache/blob/04f198bf0b2a39f7230a4304bf07747a0bddf146/examples.md
- uses: 'google-github-actions/auth@v2'
name: Acquire federated GCloud credentials...
id: auth
with:
project_id: 'extreme-cycling-441523-a9'
workload_identity_provider: 'projects/845702659200/locations/global/workloadIdentityPools/github/providers/my-repo'
service_account: [email protected]
- name: Submit
# Use npx to try to generate only
# $BAZEL generated node_modules
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
"@mdx-js/mdx": "3.1.0",
"@next/eslint-plugin-next": "15.1.7",
"@pulumi/command": "4.5.0",
"@pulumi/gcp": "^8.20.0",
"@pulumi/random": "4.17.0",
"@react-spring/rafz": "9.7.5",
"@tanstack/react-query": "5.66.9",
Expand Down
94 changes: 92 additions & 2 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions ts/pulumi/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ ts_project(
deps = [
"//:node_modules/@jest/globals",
"//:node_modules/@pulumi/aws",
"//:node_modules/@pulumi/gcp",
"//:node_modules/@pulumi/pulumi",
"//:node_modules/@types/cross-spawn",
"//:node_modules/@types/jest",
Expand All @@ -34,6 +35,7 @@ ts_project(
"//ts/pulumi/lulu.computer:pulumi_ts",
"//ts/pulumi/pleaseintroducemetoyour.dog:ts",
"//ts/pulumi/shadwell.im",
"//ts/pulumi/zemn.me/auth",
"//ts/pulumi/zemn.me/hello_world:ts",
],
)
Expand Down
8 changes: 8 additions & 0 deletions ts/pulumi/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as aws from '@pulumi/aws';
import { Budget } from '@pulumi/aws/budgets/index.js';
import { CostAllocationTag } from '@pulumi/aws/costexplorer/index.js';
import { getProject } from '@pulumi/gcp/projects/getProject';
import * as Pulumi from '@pulumi/pulumi';

import * as Baby from '#root/ts/pulumi/baby.computer/index.js';
Expand Down Expand Up @@ -98,13 +99,20 @@ export class Component extends Pulumi.ComponentResource {
{ parent: this }
);

const gcpProject = getProject({
filter: 'id: extreme-cycling-441523-a9'

}, { parent: this });

this.zemnMe = new ZemnMe.Component(
`${name}_zemn.me`,
{
zoneId: Pulumi.output(zone.me.zemn.then(z => z.id)),
domain: stage('zemn.me'),
noIndex: args.staging,
tags,
gcpProjectId: Pulumi.output(gcpProject)
.id,
},
{ parent: this }
);
Expand Down
22 changes: 22 additions & 0 deletions ts/pulumi/zemn.me/auth/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
load("//bzl:rules.bzl", "bazel_lint")
load("//ts:rules.bzl", "ts_project")

ts_project(
name = "auth",
srcs = [
"auth.ts",
],
visibility = [
"//ts/pulumi:__subpackages__",
],
deps = [
"//:node_modules/@pulumi/gcp",
"//:node_modules/@pulumi/pulumi",
"//:node_modules/@types/node",
],
)

bazel_lint(
name = "bazel_lint",
srcs = ["BUILD.bazel"],
)
53 changes: 53 additions & 0 deletions ts/pulumi/zemn.me/auth/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/**
* @fileoverview auth.zemn.me
*/

import * as gcp from '@pulumi/gcp';
import * as Pulumi from '@pulumi/pulumi';

export interface Args {
zoneId: Pulumi.Input<string>;
domain: string;
gcpProjectId: Pulumi.Input<string>;
}

// at some point i just need to make this a lib. every fucking cloud
// has its own asinine ideas about what should constitute an identifier
function clampString(baseName: string, suffixLength: number = 10, maxLength: number = 30): string {
if (suffixLength >= maxLength) {
throw new Error("Suffix length must be smaller than the maximum length");
}

return baseName.slice(0, maxLength - suffixLength)
.replaceAll(/[^A-Za-z]/g, 'z');
}

export class AuthZemnMe extends Pulumi.ComponentResource {
constructor(
name: string,
args: Args,
opts?: Pulumi.ComponentResourceOptions
) {
super('ts:pulumi:zemn.me:auth', name, args, opts);

// should be a singleton out there somewhere some day.
const service = new gcp.projects.Service(clampString(`${name}_enable_iap`), {
service: 'identitytoolkit.googleapis.com',
project: args.gcpProjectId,
}, { parent: this });


const brand = new gcp.iap.Brand(clampString(`${name}_brand`), {
supportEmail: '[email protected]',
applicationTitle: args.domain,
project: service.project
}, { parent: this })

const client = new gcp.iap.Client(clampString(`${name}_client`), {
displayName: args.domain,
brand: brand.name
}, { parent: this });

this.registerOutputs({ client })
}
}
Loading

0 comments on commit 32470a4

Please sign in to comment.