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
10 changes: 7 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ jobs:
# Fetch all branch history so that ref exists on PR and push runs.
fetch-depth: 0

- name: Test Release Safety Policy
shell: pwsh
run: powershell -ExecutionPolicy Bypass -File scripts/test_release_safety.ps1

- uses: actions/setup-node@v4
with:
node-version: 22
Expand Down Expand Up @@ -158,7 +162,7 @@ jobs:
run: fvm flutter analyze --no-fatal-infos
- name: Build Web Client
shell: pwsh
run: fvm flutter build web --no-wasm-dry-run --no-tree-shake-icons
run: fvm flutter build web --no-wasm-dry-run --no-tree-shake-icons --dart-define=ICARUS_CLOUD_ENVIRONMENT=development
- name: Run Tests
shell: pwsh
run: fvm flutter test
Expand All @@ -170,7 +174,7 @@ jobs:
cargo test --manifest-path third_party/convex_rs/Cargo.toml
- name: Build Windows Client
shell: pwsh
run: fvm flutter build windows --no-tree-shake-icons
run: fvm flutter build windows --no-tree-shake-icons --dart-define=ICARUS_CLOUD_ENVIRONMENT=development

- name: Build Windows Installer
shell: pwsh
Expand Down Expand Up @@ -278,4 +282,4 @@ jobs:
cargo test --manifest-path third_party/convex_rs/Cargo.toml

- name: Build Linux Client
run: fvm flutter build linux --no-tree-shake-icons
run: fvm flutter build linux --no-tree-shake-icons --dart-define=ICARUS_CLOUD_ENVIRONMENT=development
68 changes: 68 additions & 0 deletions .github/workflows/deploy-convex-production.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: Deploy Convex Production

on:
workflow_dispatch:
inputs:
confirmation:
description: Type deploy-production to confirm this production backend deploy.
type: string
required: true

permissions:
contents: read

jobs:
deploy:
runs-on: ubuntu-latest
environment: Production

steps:
- name: Guard Production Deploy
shell: bash
env:
CONFIRMATION: ${{ inputs.confirmation }}
run: |
if [[ "$GITHUB_REF" != "refs/heads/main" ]]; then
echo "The production Convex backend can only deploy from branch main. Current ref: $GITHUB_REF"
exit 1
fi
if [[ "$CONFIRMATION" != "deploy-production" ]]; then
echo "Confirmation must be exactly: deploy-production"
exit 1
fi

- name: Checkout Production Source
uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm

- name: Require Production Convex Deploy Key
shell: bash
env:
CONVEX_DEPLOY_KEY: ${{ secrets.CONVEX_PRODUCTION_DEPLOY_KEY }}
run: |
if [[ -z "$CONVEX_DEPLOY_KEY" ]]; then
echo "Add CONVEX_PRODUCTION_DEPLOY_KEY to the GitHub Production environment."
exit 1
fi
if [[ "$CONVEX_DEPLOY_KEY" != prod:* ]]; then
echo "CONVEX_PRODUCTION_DEPLOY_KEY must be a production deploy key with the prod: prefix."
exit 1
fi

- name: Install Convex Dependencies
run: npm ci

- name: Check Convex Types
run: npx tsc --noEmit

- name: Run Convex Tests
run: npm run test:convex

- name: Deploy Convex Production Backend
env:
CONVEX_DEPLOY_KEY: ${{ secrets.CONVEX_PRODUCTION_DEPLOY_KEY }}
run: npx convex deploy --typecheck enable --message "GitHub Actions $GITHUB_SHA"
34 changes: 34 additions & 0 deletions .github/workflows/release-desktop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,46 @@ permissions:
contents: write

jobs:
production-approval:
if: ${{ inputs.channel == 'stable' }}
runs-on: ubuntu-latest
environment: Production

steps:
- name: Guard Stable Desktop Release
shell: bash
env:
PRODUCTION_CONVEX_DEPLOYMENT_URL: ${{ vars.ICARUS_PRODUCTION_CONVEX_DEPLOYMENT_URL }}
PRODUCTION_CONVEX_CLIENT_ID: ${{ vars.ICARUS_PRODUCTION_CONVEX_CLIENT_ID }}
run: |
if [[ "$GITHUB_REF" != "refs/heads/main" ]]; then
echo "Stable desktop releases can only run from branch main. Current ref: $GITHUB_REF"
exit 1
fi
if [[ -z "$PRODUCTION_CONVEX_DEPLOYMENT_URL" || -z "$PRODUCTION_CONVEX_CLIENT_ID" ]]; then
echo "Set ICARUS_PRODUCTION_CONVEX_DEPLOYMENT_URL and ICARUS_PRODUCTION_CONVEX_CLIENT_ID before releasing stable."
exit 1
fi

build:
needs: production-approval
if: ${{ always() && (inputs.channel == 'prerelease' || needs.production-approval.result == 'success') }}
runs-on: windows-latest

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Run Release Preflight
shell: pwsh
env:
ICARUS_PRODUCTION_CONVEX_DEPLOYMENT_URL: ${{ vars.ICARUS_PRODUCTION_CONVEX_DEPLOYMENT_URL }}
ICARUS_PRODUCTION_CONVEX_CLIENT_ID: ${{ vars.ICARUS_PRODUCTION_CONVEX_CLIENT_ID }}
run: >-
powershell -ExecutionPolicy Bypass -File scripts/assert_release_preflight.ps1
-ReleaseTarget "${{ inputs.channel == 'stable' && 'stable-desktop' || 'prerelease-desktop' }}"

- uses: dart-lang/setup-dart@v1

- name: Add Pub Cache To PATH
Expand All @@ -76,6 +108,8 @@ jobs:
RELEASE_TITLE: ${{ inputs.release_title }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
POSTHOG_PROJECT_TOKEN: ${{ secrets.POSTHOG_PROJECT_TOKEN }}
ICARUS_PRODUCTION_CONVEX_DEPLOYMENT_URL: ${{ vars.ICARUS_PRODUCTION_CONVEX_DEPLOYMENT_URL }}
ICARUS_PRODUCTION_CONVEX_CLIENT_ID: ${{ vars.ICARUS_PRODUCTION_CONVEX_CLIENT_ID }}
run: |
$args = @(
"-ExecutionPolicy", "Bypass",
Expand Down
10 changes: 10 additions & 0 deletions .github/workflows/release-store.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,20 @@ permissions:
jobs:
build:
runs-on: windows-latest
environment: Production

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Run Store Release Preflight
shell: pwsh
env:
ICARUS_PRODUCTION_CONVEX_DEPLOYMENT_URL: ${{ vars.ICARUS_PRODUCTION_CONVEX_DEPLOYMENT_URL }}
ICARUS_PRODUCTION_CONVEX_CLIENT_ID: ${{ vars.ICARUS_PRODUCTION_CONVEX_CLIENT_ID }}
run: powershell -ExecutionPolicy Bypass -File scripts/assert_release_preflight.ps1 -ReleaseTarget store

- uses: dart-lang/setup-dart@v1

- name: Add Pub Cache To PATH
Expand All @@ -55,6 +63,8 @@ jobs:
shell: pwsh
env:
POSTHOG_PROJECT_TOKEN: ${{ secrets.POSTHOG_PROJECT_TOKEN }}
ICARUS_PRODUCTION_CONVEX_DEPLOYMENT_URL: ${{ vars.ICARUS_PRODUCTION_CONVEX_DEPLOYMENT_URL }}
ICARUS_PRODUCTION_CONVEX_CLIENT_ID: ${{ vars.ICARUS_PRODUCTION_CONVEX_CLIENT_ID }}
run: powershell -ExecutionPolicy Bypass -File scripts/build_store_release.ps1

- name: Upload Store Artifacts
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,13 @@ back to the installed build.
## Build

```bash
flutter build <platform>
flutter build <platform> --dart-define=ICARUS_CLOUD_ENVIRONMENT=development
```

That command makes an internal build against the named development Convex
deployment. Use the release scripts in `docs/release_process.md` for stable or
Store artifacts. They require explicit production cloud configuration.

## Versioning (Windows MSIX)

There is a helper script for bumping versions across `pubspec.yaml` and `lib/const/settings.dart`.
Expand Down
15 changes: 11 additions & 4 deletions docs/auth_flow_reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ That means the flow is:
These are the files that define the current behavior:

- `lib/main.dart`
- `lib/config/cloud_build_config.dart`
- `lib/providers/auth_provider.dart`
- `lib/collab/convex_strategy_repository.dart`
- `lib/collab/generated/`
Expand All @@ -41,11 +42,14 @@ These are the files that define the current behavior:
At startup the app initializes the Convex client and then Supabase:

```dart
final cloudBuildConfig = CloudBuildConfig.fromEnvironment(
isReleaseMode: kReleaseMode,
);
await ConvexClient.initialize(
const ConvexConfig(
deploymentUrl: 'https://majestic-eel-413.convex.cloud',
clientId: 'dev:majestic-eel-413',
operationTimeout: Duration(seconds: 30),
ConvexConfig(
deploymentUrl: cloudBuildConfig.deploymentUrl,
clientId: cloudBuildConfig.clientId,
operationTimeout: const Duration(seconds: 30),
healthCheckQuery: defaultConvexHealthCheckQuery,
),
);
Expand All @@ -60,6 +64,9 @@ await Supabase.initialize(
Why this matters:

- `ConvexClient.initialize(...)` creates the global Convex client used by the app.
- `CloudBuildConfig` selects the named development deployment for local, CI,
and prerelease builds. Stable and Store release scripts require an explicit
production URL and client ID.
- `Supabase.initialize(...)` sets up the auth provider that will issue JWTs.
- `detectSessionInUri: false` is intentional because the desktop app handles OAuth callback URIs itself instead of relying on automatic URI parsing.

Expand Down
4 changes: 2 additions & 2 deletions docs/cloud_online_release_gaps.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,8 @@ npm run snapshot:convex-contract:check
npm run audit:convex-contract
fvm flutter analyze --no-fatal-infos
fvm flutter test
fvm flutter build web --no-wasm-dry-run --no-tree-shake-icons
fvm flutter build macos --no-tree-shake-icons
fvm flutter build web --no-wasm-dry-run --no-tree-shake-icons --dart-define=ICARUS_CLOUD_ENVIRONMENT=development
fvm flutter build macos --no-tree-shake-icons --dart-define=ICARUS_CLOUD_ENVIRONMENT=development
```

On the pull request, CI also builds the Windows installer, runs
Expand Down
79 changes: 76 additions & 3 deletions docs/release_process.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,91 @@ Keep them separate. Run the workflow for the channel you actually want to publis

## Before Any Release

1. Make sure the branch contains the changes you want to ship.
1. Check the branch. Stable desktop and every Store build must run from
`main`. The release scripts stop before a version bump or build on any other
branch. Desktop prerelease builds may run from a feature branch.
2. Run the focused validation locally:
- `fvm flutter test test/update_checker_test.dart`
- `fvm flutter test test/cloud_build_config_test.dart`
- `powershell -ExecutionPolicy Bypass -File scripts/test_release_safety.ps1`
- `fvm flutter analyze`
3. Check `pubspec.yaml` and confirm the version you want to release.
4. Create or update the matching release metadata file in `release/metadata/`.
5. Write player-facing release notes in that metadata file.

## Cloud build configuration

Icarus has one named development Convex configuration in source. Local
development, CI, and desktop prerelease builds select it with
`ICARUS_CLOUD_ENVIRONMENT=development`.

An ordinary debug run defaults to development. A release-mode app with no
`ICARUS_CLOUD_ENVIRONMENT` stops during startup, so any new release entry point
must choose `development` or `production` deliberately.

Stable desktop and Store builds select `production` and require both of these
GitHub repository variables:

- `ICARUS_PRODUCTION_CONVEX_DEPLOYMENT_URL`
- `ICARUS_PRODUCTION_CONVEX_CLIENT_ID`

The production URL and client ID are public build inputs, not deploy keys. The
release scripts pass them to Flutter through a temporary Dart-defines file and
delete that file after the build. A missing value, invalid URL, or the known
development deployment stops the release before Flutter runs.

Use the deployment's canonical `https://<deployment>.convex.cloud` client URL.
The release validator does not accept custom domains, and `.convex.site` is the
HTTP Actions URL rather than the client deployment URL. See Convex's
[deployment URL guide](https://docs.convex.dev/client/react/deployment-urls)
and [system environment URL definitions](https://docs.convex.dev/production/environment-variables).

Stable desktop, Store, and production backend workflows all enter the protected
GitHub `Production` environment before they can build or publish. Desktop
prerelease skips that environment and remains available on feature branches.

For a local stable build, set the same two environment variables in the shell
before running `scripts/release_desktop.ps1`. Never put a Convex deploy key in a
Dart define or repository variable.

## One-time production Convex setup

No production deployment or key is checked into this repository. Before the
first production release:

1. Create or select the Icarus production deployment in Convex. Record its
`.convex.cloud` client URL in the repository variable above.
2. Create a deployment-scoped production deploy key with only the permissions
needed to deploy. Convex supports this in the deployment settings or with
`npx convex deployment token create github-production --deployment prod`.
See the [Convex deploy-key documentation](https://docs.convex.dev/cli/deploy-key-types).
3. Create a GitHub environment named `Production`. Restrict its deployment
branches to `main`, add any required reviewers, and add the secret
`CONVEX_PRODUCTION_DEPLOY_KEY`.
4. Add the public production URL and a stable client identifier, such as the
identifier chosen for the shipped Icarus client, to the two GitHub repository
variables in the previous section.
5. Configure the production deployment's required R2 environment values before
testing cloud media. The backend reports the exact missing names if they are
absent.

Run the manual `Deploy Convex Production` workflow from `main` and type
`deploy-production`. The workflow enters the GitHub `Production` environment,
requires a `prod:` deploy key, installs locked dependencies, runs TypeScript and
Convex tests, then runs `npx convex deploy --typecheck enable`. Convex documents
that `CONVEX_DEPLOY_KEY` selects the deployment associated with that key. See
the [`convex deploy` reference](https://docs.convex.dev/cli/reference/deploy).

The production workflow never reads `CONVEX_PREVIEW_DEPLOY_KEY`. That secret is
only for the isolated contract deployment in CI.

## Desktop Release Checklist

Use this when you want to publish the direct installer channel.

1. Go to `Actions` in GitHub.
2. Open `Release Desktop`.
3. Click `Run workflow`.
3. Confirm the selected branch is `main`, then click `Run workflow`.
4. Choose:
- `version_bump`: `none` if the version is already correct, otherwise `patch`, `minor`, or `major`
- `channel`: `stable`
Expand Down Expand Up @@ -81,7 +151,7 @@ Use this when you want to publish the Microsoft Store channel.

1. Go to `Actions` in GitHub.
2. Open `Release Store`.
3. Click `Run workflow`.
3. Confirm the selected branch is `main`, then click `Run workflow`.
4. Choose:
- `version_bump`: `none` if the version is already correct, otherwise `patch`, `minor`, or `major`
- `publish_to_store`: `false` for a dry run, `true` when you are ready to submit
Expand Down Expand Up @@ -110,6 +180,9 @@ Use this when you want to publish the Microsoft Store channel.
- `scripts/publish_prerelease_local.ps1` pushes the staged site content to `gh-pages`.
- GitHub Pages should be configured to serve `gh-pages` from `/ (root)`.
- No extra Pages deploy workflow is needed for prerelease testing.
- `release/metadata/4.6.1+97.json` is prerelease-only while the online beta
checks remain open. Do not add `stable` to its channels to make a stable
manifest build pass.
- Direct desktop installs now use a per-user install path and per-user registry registration.
- Store installs should continue to use the Microsoft Store update path only.
- The metadata file should not be a generic `template.json` in the live metadata folder, because the manifest generator treats every JSON file there as a real release entry.
Loading
Loading