diff --git a/.gitignore b/.gitignore index faf60ac..2fc1ebf 100755 --- a/.gitignore +++ b/.gitignore @@ -7,8 +7,9 @@ dist/ *.tsbuildinfo coverage/ -# icp-cli / dfx state -.icp/ +# icp-cli / dfx state. `.icp/data/` holds the mainnet canister ids and is +# committed, as icp-cli advises: without it, a deploy creates new canisters. +.icp/cache/ .dfx/ # Environment diff --git a/.icp/data/mappings/production.ids.json b/.icp/data/mappings/production.ids.json new file mode 100644 index 0000000..0883d7b --- /dev/null +++ b/.icp/data/mappings/production.ids.json @@ -0,0 +1,4 @@ +{ + "backend": "xeka7-ryaaa-aaaal-qb57a-cai", + "frontend": "4lidq-zqaaa-aaaap-abkbq-cai" +} \ No newline at end of file diff --git a/README.md b/README.md index 0990f09..bbabe07 100755 --- a/README.md +++ b/README.md @@ -156,9 +156,17 @@ backend uses it automatically. ## Deploying to mainnet ```bash -icp deploy -e production +icp deploy -e production --no-create # both canisters +icp deploy frontend -e production --no-create # the frontend only ``` +The deploy upgrades the canisters recorded in `.icp/data/mappings/production.ids.json`: backend +`xeka7-ryaaa-aaaal-qb57a-cai` and frontend `4lidq-zqaaa-aaaap-abkbq-cai`. `--no-create` makes it stop +rather than create a canister that is not recorded there. Do not deploy with `-e ic`: that is icp-cli's +built-in mainnet environment, which records none of these ids, so it creates new canisters. A new +frontend is a new origin, which gives every user a new principal, and the custom domain would still +point at the old one. + The `production` environment uses the vetKD key `key_1`, keeps the AI assistant off and sets strict limits (`icp.yaml`). The frontend reads the backend's id from the asset canister's `ic_env` cookie on `*.icp0.io`, and from `frontend/src/lib/origins.ts` on a custom domain ([Custom domain](#custom-domain)). diff --git a/frontend/tests/production.test.ts b/frontend/tests/production.test.ts new file mode 100644 index 0000000..b8810f6 --- /dev/null +++ b/frontend/tests/production.test.ts @@ -0,0 +1,24 @@ +/** + * B3Note's mainnet canisters (README, "Deploying to mainnet"). icp-cli deploys + * the `production` environment to the ids in `.icp/data/mappings`, and creates + * a new canister for any it cannot find there. A new frontend is a new origin, + * which gives every user a new principal, so the ids recorded there must stay + * the ones the app signs in for and calls. + */ +import { readFileSync } from "node:fs" +import { dirname, join } from "node:path" +import { fileURLToPath } from "node:url" +import { describe, expect, it } from "vitest" +import { PRODUCTION } from "../src/lib/origins" + +const root = join(dirname(fileURLToPath(import.meta.url)), "../..") + +describe("production's canisters", () => { + it("are recorded for icp-cli as the ones the app signs in for and calls", () => { + const ids = JSON.parse(readFileSync(join(root, ".icp/data/mappings/production.ids.json"), "utf8")) + expect(ids).toEqual({ + backend: PRODUCTION.backend, + frontend: new URL(PRODUCTION.origin).hostname.replace(/\.icp0\.io$/, ""), + }) + }) +}) diff --git a/icp.yaml b/icp.yaml index 3ee053e..6a5fddd 100644 --- a/icp.yaml +++ b/icp.yaml @@ -1,7 +1,8 @@ # yaml-language-server: $schema=https://github.com/dfinity/icp-cli/raw/refs/tags/v1.6.0/docs/schemas/icp-yaml-schema.json # # B3Note: `icp network start -d && icp deploy` for a local deployment, -# `icp deploy -e production` for mainnet. +# `icp deploy -e production --no-create` for mainnet, never `-e ic` +# (README, "Deploying to mainnet"). canisters: - name: backend diff --git a/package.json b/package.json index b8cc1df..04f5d6a 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "dev": "pnpm --dir frontend dev", "dev:pocketic": "pnpm --dir frontend dev:pocketic", "deploy": "icp deploy", - "deploy:production": "icp deploy -e production" + "deploy:production": "icp deploy -e production --no-create" }, "packageManager": "pnpm@10.28.0" }