Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Deploy Static Site

on:
push:
branches:
- master
- aws-deploy
workflow_dispatch:

permissions:
id-token: write
contents: read

env:
AWS_REGION: ${{ vars.AWS_REGION }}
S3_BUCKET: ${{ vars.S3_BUCKET }}
CLOUDFRONT_DISTRIBUTION_ID: ${{ vars.CLOUDFRONT_DISTRIBUTION_ID }}
NUXT_PUBLIC_SITE_URL: ${{ github.ref == 'refs/heads/master' && secrets.NUXT_PUBLIC_SITE_URL || vars.PREVIEW_SITE_URL }}
GH_TOKEN: ${{ secrets.GH_TOKEN }}
NUXT_PUBLIC_ASSET_KEY: ${{ secrets.NUXT_PUBLIC_ASSET_KEY }}

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: latest

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Show site URL
if: github.ref != 'refs/heads/master'
run: echo "NUXT_PUBLIC_SITE_URL=${NUXT_PUBLIC_SITE_URL}"

- name: Generate reports
run: bun run generate-reports

- name: Generate static site
run: bun run generate

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ${{ env.AWS_REGION }}

- name: Sync artifacts to S3
run: aws s3 sync .output/public "s3://${S3_BUCKET}" --delete

- name: Invalidate CloudFront
run: aws cloudfront create-invalidation --distribution-id "${CLOUDFRONT_DISTRIBUTION_ID}" --paths "/*"
1 change: 1 addition & 0 deletions infra/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.pulumi/
10 changes: 10 additions & 0 deletions infra/Pulumi.dev.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
encryptionsalt: v1:W1NLKXoFxV4=:v1:S5quyyMBvgH4qAzD:tYNPw7qdVcUbCoFdkwH+URbo1ukeqQ==
config:
aws:region: us-west-2
projectm-infra:bucketName: prjm
projectm-infra:cloudfrontPriceClass: PriceClass_100
projectm-infra:githubOwner: projectM-visualizer
projectm-infra:githubRefs: '["ref:refs/heads/*","ref:refs/tags/*","ref:refs/pull/*"]'
projectm-infra:githubRepo: projectm-visualizer.org
projectm-infra:primaryDomain: projectm-visualizer.org
projectm-infra:hostedZoneId: Z0970442162ZXM1J1N8GK
7 changes: 7 additions & 0 deletions infra/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
name: projectm-infra
runtime:
name: nodejs
options:
typescript: true
main: index.ts
description: Infrastructure for the ProjectM static site on AWS.
79 changes: 79 additions & 0 deletions infra/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Infrastructure

Manage the static site infrastructure with Pulumi.

## Prerequisites

- Pulumi CLI
- AWS credentials with permissions to manage S3, CloudFront, ACM, Route53, and IAM

## Setup

1. Install dependencies:
```bash
cd infra
npm install
```
2. Log into the shared S3 backend (only needs to be done once per environment):
```bash
AWS_PROFILE=projectm pulumi login s3://pulumi-state-projectm
```
3. Create a stack (example `dev`) if it does not exist:
```bash
pulumi stack init dev
```
4. Configure required values:
```bash
pulumi config set bucketName prjm
pulumi config set githubOwner projectM-visualizer
pulumi config set githubRepo projectm-visualizer.org
pulumi config set githubRefs '["ref:refs/heads/master"]'
# Allow additional refs as needed, for example:
pulumi config set githubRefs '["ref:refs/heads/master","ref:refs/heads/*","ref:refs/tags/*","ref:refs/pull/*"]'
pulumi config set aws:region your-app-region
Comment on lines +28 to +33
Copy link

Copilot AI Oct 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent indentation in the code block. Lines 28-30 have extra leading spaces compared to line 27, which makes the commands appear misaligned. Ensure all lines have consistent indentation (no leading spaces after the newline).

Suggested change
pulumi config set githubOwner projectM-visualizer
pulumi config set githubRepo projectm-visualizer.org
pulumi config set githubRefs '["ref:refs/heads/master"]'
# Allow additional refs as needed, for example:
pulumi config set githubRefs '["ref:refs/heads/master","ref:refs/heads/*","ref:refs/tags/*","ref:refs/pull/*"]'
pulumi config set aws:region your-app-region
pulumi config set githubOwner projectM-visualizer
pulumi config set githubRepo projectm-visualizer.org
pulumi config set githubRefs '["ref:refs/heads/master"]'
# Allow additional refs as needed, for example:
pulumi config set githubRefs '["ref:refs/heads/master","ref:refs/heads/*","ref:refs/tags/*","ref:refs/pull/*"]'
pulumi config set aws:region your-app-region

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Oct 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 33 has inconsistent indentation with extra leading spaces. This should align with the other commands in the code block to maintain consistency.

Suggested change
pulumi config set aws:region your-app-region
pulumi config set aws:region your-app-region

Copilot uses AI. Check for mistakes.
```
5. Optional configuration:
- `cloudfrontPriceClass` (`PriceClass_100`, `PriceClass_200`, `PriceClass_All`)
- `primaryDomain` and `alternateDomains` to enable custom domains
- `hostedZoneId` to request an ACM certificate via DNS validation
- `certificateArn` to reuse an existing certificate instead of provisioning one
- `oidcProviderArn` to reference an existing GitHub OIDC provider
- `githubRoleName` to override the IAM role name

6. Deploy:
```bash
AWS_PROFILE=projectm PULUMI_CONFIG_PASSPHRASE=projectm pulumi up
```

Outputs include the CloudFront distribution details and the IAM role ARN.

### State

State lives in `s3://pulumi-state-projectm` (versioned). Set `AWS_PROFILE=projectm` and `PULUMI_CONFIG_PASSPHRASE=projectm` when running Pulumi commands so AWS calls and encrypted config values work consistently.

## GitHub Actions

Set these repository secrets and variables before running the deployment workflow:

- `AWS_ROLE_ARN` (secret): ARN of the IAM role exported by Pulumi.
- `GH_TOKEN` (secret): GitHub token with `repo` scope for `generate-reports`.
- `NUXT_PUBLIC_ASSET_KEY` (secret): Encryption key used by `generate-reports`.
- `vars.PREVIEW_SITE_URL`: CloudFront preview URL (for example, `https://d15wenzbsa5dzp.cloudfront.net`).
- `secrets.NUXT_PUBLIC_SITE_URL`: Production URL used on the `master` branch (for example, `https://projectm-visualizer.org`).
- `vars.AWS_REGION`: AWS region for S3 operations (for example, `us-west-2`).
- `vars.S3_BUCKET`: Target S3 bucket name (`prjm`).
- `vars.CLOUDFRONT_DISTRIBUTION_ID`: Distribution ID exported by Pulumi.

### CloudFront Access Logging

Provision the log bucket and enable CloudFront logging with the helper script (run once per environment):

```bash
cd infra
AWS_PROFILE=projectm AWS_SDK_LOAD_CONFIG=1 node scripts/enable-cloudfront-logging.mjs
```

By default this creates `projectm-visualizer-cloudfront-logs` in `us-west-2` and configures the distribution to write compressed logs (cookies included) under the `cloudfront/` prefix.


The workflow runs on pushes to `master` and can also be triggered manually.
Loading