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
31 changes: 31 additions & 0 deletions .github/workflows/deploy-production.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Deploy production

on:
workflow_dispatch:
inputs:
tag:
description: 'Release tag being deployed, such as v1.2.3'
required: true
type: string

permissions:
contents: read

jobs:
deploy:
name: Deploy to production
uses: ./.github/workflows/_deploy-environment.yml
with:
tag: ${{ inputs.tag }}
environment: production
secrets: inherit

health-check:
name: Health check production
needs: deploy
uses: ./.github/workflows/deploy-health-check.yml
with:
tag: ${{ inputs.tag }}
environment: production
profile: cloud
secrets: inherit
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
**A daily planner for minimalists. Organize your day and lock-in.**

<img width="1512" height="860" alt="week-view-2026-06" src="https://github.com/user-attachments/assets/6dcfd741-883d-401c-b8e2-97300b1dd925" />
<img width="1508" height="835" alt="day-view-2026-06" src="https://github.com/user-attachments/assets/adce91f8-40b1-4990-afa1-859ab61a7dab" />


## Why Try Compass?

Expand Down
17 changes: 17 additions & 0 deletions docs/CI-CD/workflows.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Compass uses GitHub Actions for continuous integration, Docker Hub for image dis
| Release on main | Push to `main` | Auto-increments patch version, publishes Docker images, then deploys staging |
| Publish Docker images | Reusable workflow / manual dispatch / manual `v*.*.*` tag push | Builds and pushes Docker images only |
| Deploy staging | Reusable workflow / manual dispatch | Pulls published images on staging, restarts the stack, then runs deploy health checks |
| Deploy production | Manual dispatch | Deploys a release tag to production, then runs cloud deploy health checks |
| Deploy health check | Reusable workflow | Validates the deployed staging stack and alerts Discord on failure |
| Sync docs to compass-docs | Push to `main` touching `docs/**` | Mirrors this `docs/` directory to docs.compasscalendar.com |

Expand Down Expand Up @@ -127,3 +128,19 @@ Secrets and variables are split between repository level (shared across workflow
| `BACKEND_API_URL` | Staging backend API URL |
| `FRONTEND_URL` | Staging frontend URL |
| `GOOGLE_CLIENT_ID` | OAuth client ID |

---

## Production Deploy

Source: [`.github/workflows/deploy-production.yml`](../../.github/workflows/deploy-production.yml)

Production deploys are manual-only. Run `Deploy production` from GitHub Actions
with an existing release tag, such as `v1.2.3`; it is not called by
`release-on-main.yml` and does not run automatically after PR merges.

The workflow deploys to the GitHub `production` environment through
`_deploy-environment.yml`, builds an environment-specific web image tagged
`switchbacktech/compass-web:production-<version>`, then runs
`deploy-health-check.yml` with the `cloud` profile. Production is expected to use
external MongoDB and SuperTokens Cloud rather than self-hosted data services.
16 changes: 16 additions & 0 deletions self-host/docker-compose.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,22 @@ describe("staging deploy workflow", () => {
expect(workflow).toContain("profile: selfhosted");
});

it("provides a manual production deploy workflow with cloud health checks", () => {
const workflow = readRepoFile(".github/workflows/deploy-production.yml");

expect(workflow).toContain("workflow_dispatch:");
expect(workflow).not.toContain("workflow_call:");
expect(workflow).toContain(
"uses: ./.github/workflows/_deploy-environment.yml",
);
expect(workflow).toContain("environment: production");
expect(workflow).toContain(
"uses: ./.github/workflows/deploy-health-check.yml",
);
expect(workflow).toContain("needs: deploy");
expect(workflow).toContain("profile: cloud");
});

it("provides a reusable deploy health check workflow with Discord failure alerts", () => {
const workflow = readRepoFile(".github/workflows/deploy-health-check.yml");

Expand Down